mirror of https://github.com/kcal-app/kcal.git
Use slugs for recipe and food routes
This commit is contained in:
parent
784bc490dc
commit
ab10dd0342
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\Traits\Journalable;
|
||||||
|
use App\Models\Traits\Sluggable;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int id
|
* @property int id
|
||||||
|
@ -21,9 +24,11 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
* @property \Illuminate\Support\Carbon created_at
|
* @property \Illuminate\Support\Carbon created_at
|
||||||
* @property \Illuminate\Support\Carbon updated_at
|
* @property \Illuminate\Support\Carbon updated_at
|
||||||
*/
|
*/
|
||||||
class Food extends JournalableModel
|
class Food extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use Sluggable;
|
||||||
|
use Journalable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
|
|
@ -54,7 +54,7 @@ class JournalEntry extends Model
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected $with = ['user', 'foods:id,name', 'recipes:id,name'];
|
protected $with = ['user', 'foods:id,name,slug', 'recipes:id,name,slug'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the User this entry belongs to.
|
* Get the User this entry belongs to.
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\Traits\Journalable;
|
||||||
|
use App\Models\Traits\Sluggable;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,9 +30,11 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
* @method float sodiumTotal Get total sodium.
|
* @method float sodiumTotal Get total sodium.
|
||||||
* @method float sodiumPerServing Get per serving sodium.
|
* @method float sodiumPerServing Get per serving sodium.
|
||||||
*/
|
*/
|
||||||
class Recipe extends JournalableModel
|
class Recipe extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use Journalable;
|
||||||
|
use Sluggable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models\Traits;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use App\Models\JournalEntry;
|
||||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||||
|
|
||||||
abstract class JournalableModel extends Model
|
trait Journalable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get all of the journal entries for the recipe.
|
* Get all of the journal entries for the recipe.
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models\Traits;
|
||||||
|
|
||||||
|
use Cviebrock\EloquentSluggable\Sluggable as SluggableBase;
|
||||||
|
use Cviebrock\EloquentSluggable\SluggableScopeHelpers;
|
||||||
|
|
||||||
|
trait Sluggable
|
||||||
|
{
|
||||||
|
use SluggableBase;
|
||||||
|
use SluggableScopeHelpers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function sluggable(): array
|
||||||
|
{
|
||||||
|
return ['slug' => ['source' => 'name']];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function getRouteKeyName(): string
|
||||||
|
{
|
||||||
|
return $this->getSlugKeyName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function getRouteKey(): string
|
||||||
|
{
|
||||||
|
return $this->getSlugKey();
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.0",
|
"php": "^8.0",
|
||||||
|
"cviebrock/eloquent-sluggable": "^8.0",
|
||||||
"fideloper/proxy": "^4.4",
|
"fideloper/proxy": "^4.4",
|
||||||
"fruitcake/laravel-cors": "^2.0",
|
"fruitcake/laravel-cors": "^2.0",
|
||||||
"guzzlehttp/guzzle": "^7.0.1",
|
"guzzlehttp/guzzle": "^7.0.1",
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "d33692a22f60e4e61e7aa7195979cdfd",
|
"content-hash": "15b3829c7b58db14299bd2c323539f47",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "asm89/stack-cors",
|
"name": "asm89/stack-cors",
|
||||||
|
@ -118,6 +118,147 @@
|
||||||
],
|
],
|
||||||
"time": "2020-08-18T23:57:15+00:00"
|
"time": "2020-08-18T23:57:15+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "cocur/slugify",
|
||||||
|
"version": "v4.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/cocur/slugify.git",
|
||||||
|
"reference": "3f1ffc300f164f23abe8b64ffb3f92d35cec8307"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/cocur/slugify/zipball/3f1ffc300f164f23abe8b64ffb3f92d35cec8307",
|
||||||
|
"reference": "3f1ffc300f164f23abe8b64ffb3f92d35cec8307",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": ">=7.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/config": "<3.4 || >=4,<4.3",
|
||||||
|
"symfony/dependency-injection": "<3.4 || >=4,<4.3",
|
||||||
|
"symfony/http-kernel": "<3.4 || >=4,<4.3",
|
||||||
|
"twig/twig": "<2.12.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel/framework": "~5.1",
|
||||||
|
"latte/latte": "~2.2",
|
||||||
|
"league/container": "^2.2.0",
|
||||||
|
"mikey179/vfsstream": "~1.6.8",
|
||||||
|
"mockery/mockery": "^1.3",
|
||||||
|
"nette/di": "~2.4",
|
||||||
|
"phpunit/phpunit": "^5.7.27",
|
||||||
|
"pimple/pimple": "~1.1",
|
||||||
|
"plumphp/plum": "~0.1",
|
||||||
|
"symfony/config": "^3.4 || ^4.3 || ^5.0",
|
||||||
|
"symfony/dependency-injection": "^3.4 || ^4.3 || ^5.0",
|
||||||
|
"symfony/http-kernel": "^3.4 || ^4.3 || ^5.0",
|
||||||
|
"twig/twig": "^2.12.1 || ~3.0",
|
||||||
|
"zendframework/zend-modulemanager": "~2.2",
|
||||||
|
"zendframework/zend-servicemanager": "~2.2",
|
||||||
|
"zendframework/zend-view": "~2.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Cocur\\Slugify\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Florian Eckerstorfer",
|
||||||
|
"email": "florian@eckerstorfer.co",
|
||||||
|
"homepage": "https://florian.ec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ivo Bathke",
|
||||||
|
"email": "ivo.bathke@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Converts a string into a slug.",
|
||||||
|
"keywords": [
|
||||||
|
"slug",
|
||||||
|
"slugify"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/cocur/slugify/issues",
|
||||||
|
"source": "https://github.com/cocur/slugify/tree/master"
|
||||||
|
},
|
||||||
|
"time": "2019-12-14T13:04:14+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cviebrock/eloquent-sluggable",
|
||||||
|
"version": "8.0.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/cviebrock/eloquent-sluggable.git",
|
||||||
|
"reference": "1b693b333de9080380340facf3806c644a949ad7"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/cviebrock/eloquent-sluggable/zipball/1b693b333de9080380340facf3806c644a949ad7",
|
||||||
|
"reference": "1b693b333de9080380340facf3806c644a949ad7",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"cocur/slugify": "^4.0",
|
||||||
|
"illuminate/config": "^8.0",
|
||||||
|
"illuminate/database": "^8.0",
|
||||||
|
"illuminate/support": "^8.0",
|
||||||
|
"php": "^7.3|^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"limedeck/phpunit-detailed-printer": "^6.0",
|
||||||
|
"mockery/mockery": "^1.4.2",
|
||||||
|
"orchestra/database": "^6.0",
|
||||||
|
"orchestra/testbench": "^6.0",
|
||||||
|
"phpunit/phpunit": "^9.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Cviebrock\\EloquentSluggable\\ServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Cviebrock\\EloquentSluggable\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Colin Viebrock",
|
||||||
|
"email": "colin@viebrock.ca"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Easy creation of slugs for your Eloquent models in Laravel",
|
||||||
|
"homepage": "https://github.com/cviebrock/eloquent-sluggable",
|
||||||
|
"keywords": [
|
||||||
|
"eloquent",
|
||||||
|
"eloquent-sluggable",
|
||||||
|
"laravel",
|
||||||
|
"lumen",
|
||||||
|
"slug",
|
||||||
|
"sluggable"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/cviebrock/eloquent-sluggable/issues",
|
||||||
|
"source": "https://github.com/cviebrock/eloquent-sluggable/tree/8.0.2"
|
||||||
|
},
|
||||||
|
"time": "2020-11-29T18:53:58+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "dnoegel/php-xdg-base-dir",
|
"name": "dnoegel/php-xdg-base-dir",
|
||||||
"version": "v0.1.1",
|
"version": "v0.1.1",
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What attributes do we use to build the slug?
|
||||||
|
* This can be a single field, like "name" which will build a slug from:
|
||||||
|
*
|
||||||
|
* $model->name;
|
||||||
|
*
|
||||||
|
* Or it can be an array of fields, like ["name", "company"], which builds a slug from:
|
||||||
|
*
|
||||||
|
* $model->name . ' ' . $model->company;
|
||||||
|
*
|
||||||
|
* If you've defined custom getters in your model, you can use those too,
|
||||||
|
* since Eloquent will call them when you request a custom attribute.
|
||||||
|
*
|
||||||
|
* Defaults to null, which uses the toString() method on your model.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'source' => null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum length of a generated slug. Defaults to "null", which means
|
||||||
|
* no length restrictions are enforced. Set it to a positive integer if you
|
||||||
|
* want to make sure your slugs aren't too long.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'maxLength' => null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you are setting a maximum length on your slugs, you may not want the
|
||||||
|
* truncated string to split a word in half. The default setting of "true"
|
||||||
|
* will ensure this, e.g. with a maxLength of 12:
|
||||||
|
*
|
||||||
|
* "my source string" -> "my-source"
|
||||||
|
*
|
||||||
|
* Setting it to "false" will simply truncate the generated slug at the
|
||||||
|
* desired length, e.g.:
|
||||||
|
*
|
||||||
|
* "my source string" -> "my-source-st"
|
||||||
|
*/
|
||||||
|
|
||||||
|
'maxLengthKeepWords' => true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If left to "null", then use the cocur/slugify package to generate the slug
|
||||||
|
* (with the separator defined below).
|
||||||
|
*
|
||||||
|
* Set this to a closure that accepts two parameters (string and separator)
|
||||||
|
* to define a custom slugger. e.g.:
|
||||||
|
*
|
||||||
|
* 'method' => function( $string, $sep ) {
|
||||||
|
* return preg_replace('/[^a-z]+/i', $sep, $string);
|
||||||
|
* },
|
||||||
|
*
|
||||||
|
* Otherwise, this will be treated as a callable to be used. e.g.:
|
||||||
|
*
|
||||||
|
* 'method' => array('Str','slug'),
|
||||||
|
*/
|
||||||
|
|
||||||
|
'method' => null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Separator to use when generating slugs. Defaults to a hyphen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'separator' => '-',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enforce uniqueness of slugs? Defaults to true.
|
||||||
|
* If a generated slug already exists, an incremental numeric
|
||||||
|
* value will be appended to the end until a unique slug is found. e.g.:
|
||||||
|
*
|
||||||
|
* my-slug
|
||||||
|
* my-slug-1
|
||||||
|
* my-slug-2
|
||||||
|
*/
|
||||||
|
|
||||||
|
'unique' => true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you are enforcing unique slugs, the default is to add an
|
||||||
|
* incremental value to the end of the base slug. Alternatively, you
|
||||||
|
* can change this value to a closure that accepts three parameters:
|
||||||
|
* the base slug, the separator, and a Collection of the other
|
||||||
|
* "similar" slugs. The closure should return the new unique
|
||||||
|
* suffix to append to the slug.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'uniqueSuffix' => null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should we include the trashed items when generating a unique slug?
|
||||||
|
* This only applies if the softDelete property is set for the Eloquent model.
|
||||||
|
* If set to "false", then a new slug could duplicate one that exists on a trashed model.
|
||||||
|
* If set to "true", then uniqueness is enforced across trashed and existing models.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'includeTrashed' => false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of slug names that can never be used for this model,
|
||||||
|
* e.g. to prevent collisions with existing routes or controller methods, etc..
|
||||||
|
* Defaults to null (i.e. no reserved names).
|
||||||
|
* Can be a static array, e.g.:
|
||||||
|
*
|
||||||
|
* 'reserved' => array('add', 'delete'),
|
||||||
|
*
|
||||||
|
* or a closure that returns an array of reserved names.
|
||||||
|
* If using a closure, it will accept one parameter: the model itself, and should
|
||||||
|
* return an array of reserved names, or null. e.g.
|
||||||
|
*
|
||||||
|
* 'reserved' => function( Model $model) {
|
||||||
|
* return $model->some_method_that_returns_an_array();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* In the case of a slug that gets generated with one of these reserved names,
|
||||||
|
* we will do:
|
||||||
|
*
|
||||||
|
* $slug .= $separator + "1"
|
||||||
|
*
|
||||||
|
* and continue from there.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'reserved' => null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to update the slug value when a model is being
|
||||||
|
* re-saved (i.e. already exists). Defaults to false, which
|
||||||
|
* means slugs are not updated.
|
||||||
|
*
|
||||||
|
* Be careful! If you are using slugs to generate URLs, then
|
||||||
|
* updating your slug automatically might change your URLs which
|
||||||
|
* is probably not a good idea from an SEO point of view.
|
||||||
|
* Only set this to true if you understand the possible consequences.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'onUpdate' => false,
|
||||||
|
|
||||||
|
];
|
|
@ -14,6 +14,7 @@ class CreateFoodsTable extends Migration
|
||||||
Schema::create('foods', function (Blueprint $table) {
|
Schema::create('foods', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
|
$table->string('slug')->unique();
|
||||||
$table->string('detail')->nullable();
|
$table->string('detail')->nullable();
|
||||||
$table->string('brand')->nullable();
|
$table->string('brand')->nullable();
|
||||||
$table->unsignedFloat('serving_size');
|
$table->unsignedFloat('serving_size');
|
||||||
|
|
|
@ -16,6 +16,7 @@ class CreateRecipesTable extends Migration
|
||||||
Schema::create('recipes', function (Blueprint $table) {
|
Schema::create('recipes', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
|
$table->string('slug')->unique();
|
||||||
$table->longText('description');
|
$table->longText('description');
|
||||||
$table->unsignedInteger('servings');
|
$table->unsignedInteger('servings');
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
Loading…
Reference in New Issue