How to Use a Slug for a URL - laravel

I am trying to use slugs as a way to display links on my URL. For example instead of using:
http://localhost:8000/product/1
I want to use...
http://localhost:8000/product/blue-shirts
So far I managed to add slugs via the package cviebrock/eloquent-sluggable. What should I use for my route and view?
<?php
use Sluggable;
public function sluggable()
{
return [
'slug' => [
'source' => 'product_name'
]
];
}

Related

laravel endpoint hide field

How can i hide some fields ?
i want to hide the file field
Eloquent :
$reports = Report::select('id', 'file','company_id', 'title', 'year', 'created_at')
->orderBy('id', 'desc')
->paginate(10);
return ReportResource::collection($reports);
Model :
...
public function getFileSizeAttribute()
{
return Storage::disk('files')->size($this->attributes['file']);
}
....
ReportResource:
...
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'year' => $this->year,
'views' => $this->whenNotNull($this->views),
'file' => $this->whenNotNull($this->file), <-- i want to hide the file field
'file_size' => $this->fileSize, <-- but always show file_size
'created_at' => $this->created_at,
'company' => new CompanyResource($this->company),
];
}
to get file_size field i must select the file field , because it's depends on it to calculate the file size.
but i want to hide the file field before send the response.
i know i can use the protected $hidden = [] method in the model , but i don't want that, because file field it's required on others place. i just want to hide it on this endpoint only.
Since you are using API resources the best and clean way to do this is by using a Resource class for your collection.
Said that, you will have 3 Resources:
The first one, as it is, just for retrieving a single Model with file and file_size attributes. The one you already have ReportResource.php
...
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'year' => $this->year,
'views' => $this->whenNotNull($this->views),
'file' => $this->whenNotNull($this->file),
'file_size' => $this->fileSize,
'created_at' => $this->created_at,
'company' => new CompanyResource($this->company),
];
}
A new second resource to be used in your endpoint, without the file attribute. IE: ReportIndexResource.php
...
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'year' => $this->year,
'views' => $this->whenNotNull($this->views),
'file_size' => $this->fileSize,
'created_at' => $this->created_at,
'company' => new CompanyResource($this->company),
];
}
Now you need to create a Resource collection which explicitly defines the Model Resource to use. IE: ReportCollection.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class ReportCollection extends ResourceCollection
{
/**
* The resource that this resource collects.
*
* #var string
*/
public $collects = ReportIndexResource::class;
}
Finally, use this new resource collection in your endpoint
$reports = Report::select('id', 'file','company_id', 'title', 'year', 'created_at')
->orderBy('id', 'desc')
->paginate(10);
return new ReportCollection($reports);
Of course, you can make use of makeHidden() method, but IMO is better to write a little more code and avoid a non desired attribute in your response because you forgot to make it hidden.
Also, in case you make use of makeHidden() method and you want to show the attribute in a future, you will have to update all your queries instead of a silgle resource file.
If you want to make it Hide From All Returns , you can Do this in model
protected $hidden = ['file'];
and if you want to do it temporirly with this query , you can Use MakeHidden method
$users = $reports->makeHidden(['file']);
It's clear in laravel docs , take a look
https://laravel.com/docs/9.x/eloquent-collections#method-makeHidden

How set uploaded avatar in this.$page.props.user with inertiajs?

In Laravel 8 app with inertiajs/inertia-vue 0.7/vuejs2 with fortify (but without jetstream)
I use "spatie/laravel-medialibrary": "^9.9" for avatar uploading like
$loggedUser = auth()->user();
$avatar_file_path = $avatarImageUploadedFile->getPathName();
$loggedUser->addMedia( $avatar_file_path )->toMediaCollection('avatar');
and it works, but in which way can I use avatar in on client part when I use
this.$page.props.user
in vue components properties to check which user is logged and show his info?
Thanks!
You can do this with the 'Shared data' feature via the HandleInertiaRequests middleware.
For example, to share user info you can do the following:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
class HandleInertiaRequests extends Middleware
{
public function share(Request $request)
{
return array_merge(parent::share($request), [
'user' => function () {
return Auth::user() ? [
'id' => Auth::user()->id,
'name' => Auth::user()->name,
'email' => Auth::user()->email,
// get path to avatar
'avatar' => Storage::url('avatar-of-the-user.jpg'),
] : null;
},
]);
}
}
Client side you can then access the avatar's URL with this.$page.props.user.avatar.

How to generate dummy images in PHP Laravel?

I want to make dummy data on my home page, including showing dummy images. How can I generate images?
In the factory method, while seeding, do something like this.
$factory->define(Post::class, function (Faker $faker) {
return [
'image'=>'https://source.unsplash.com/random',
];
});
Now every time when you run the factory to seed, it will put that link in the image field. This link will give you a random image each time from unsplash.
Simply add photo dimensions after the URL (ex: /800x600)
If you just want to look your homepage "live" with dummy images and without actually uploading the image, you can show random images using this site:
http://lorempixel.com/
<img src="http://lorempixel.com/400/200/sports/" />
You can also store that image path in the database while seeding.
Thanks
In the following turorial show how to add images in the seeder.
https://www.5balloons.info/faker-images-in-laravel/#
Use the following method:
'image' => $faker->image('public/storage/images',640,480, null, false),
<?php
/* #var $factory \Illuminate\Database\Eloquent\Factory */
use App\Product;
use Faker\Generator as Faker;
$factory->define(Product::class, function (Faker $faker) {
return [
'name' => $faker->word,
'short_description' => $faker->sentence,
'description' => $faker->paragraph,
'category_id' => function () {
return factory(App\Category::class)->create()->id;
},
'amount' => $faker->randomFloat(2, 0, 10000),
'image' => $faker->image('public/storage/images',640,480, null, false),
];
});
You could use faker to create a seeder file that places some dummy images into your database. Faker comes pre-installed with laravel.
May be it could help someone who wants to work with Ecommerce dummy product images -
public function definition()
{
$randomImages =[
'https://m.media-amazon.com/images/I/41WpqIvJWRL._AC_UY436_QL65_.jpg',
'https://m.media-amazon.com/images/I/61ghDjhS8vL._AC_UY436_QL65_.jpg',
'https://m.media-amazon.com/images/I/61c1QC4lF-L._AC_UY436_QL65_.jpg',
'https://m.media-amazon.com/images/I/710VzyXGVsL._AC_UY436_QL65_.jpg',
'https://m.media-amazon.com/images/I/61EPT-oMLrL._AC_UY436_QL65_.jpg',
'https://m.media-amazon.com/images/I/71r3ktfakgL._AC_UY436_QL65_.jpg',
'https://m.media-amazon.com/images/I/61CqYq+xwNL._AC_UL640_QL65_.jpg',
'https://m.media-amazon.com/images/I/71cVOgvystL._AC_UL640_QL65_.jpg',
'https://m.media-amazon.com/images/I/71E+oh38ZqL._AC_UL640_QL65_.jpg',
'https://m.media-amazon.com/images/I/61uSHBgUGhL._AC_UL640_QL65_.jpg',
'https://m.media-amazon.com/images/I/71nDK2Q8HAL._AC_UL640_QL65_.jpg'
];
return [
'name' => fake()->sentence(5),
'price' => fake()->randomFloat(2, 10, 1000),
'image' => $randomImages[rand(0, 10)]
];
}
For me, it's simply enough to get some real-dummy image for development test purpose.

unique value with custom request laravel 5.3

i have custom request in laravel ..
this is the code
public function rules()
{
if($this->ajax())
{
return [];
}
else
{
return
[
'username'=> 'required|min:3|max:30|unique:users',
'password'=> 'required|min:6',
'email'=>'required|min:3|max:35|unique:users',
'permission'=>'required',
'phone'=>'required',
'division'=>'required',
];
}
}
and i need to to ignore the current id from validation
i tried this
public function rules()
{
if($this->ajax())
{
return [];
}
else
{
return
[
'username'=> 'required|min:3|max:30|unique:users,id'.$this->id,
'password'=> 'required|min:6',
'email'=>'required|min:3|max:35|unique:users',
'permission'=>'required',
'phone'=>'required',
'division'=>'required',
];
}
}
but its ignoring the whole user name from validation not just the current id ..
Use auth()->user()->id instead of $this->id to get current user's ID.
Also, I'm not sure about the syntax you're using when trying to add ignoring ID. From unique() rule docs:
To instruct the validator to ignore the user's ID, we'll use the Rule class to fluently define the rule. In this example, we'll also specify the validation rules as an array instead of using the | character to delimit the rules:
use Illuminate\Validation\Rule;
Validator::make($data, [
'email' => [
'required',
Rule::unique('users')->ignore($user->id),
],
]);

Yii2: can I $this->render(..) and then execute sql command?

I have an idea how speed up page load. I have sql command that I need to execute in controller. What if I try to execute after rendering page? Rendering vars (model) does not depend on it.
public function actionIndex()
{
$model = new Model();
...
$this->render('index', [
'model' => $model,
]);
Yii::$app->db->createCommand('UPDATE ...')->execute();
return;
}
You could use "afterRender" to do some stuff if your really want to execute something after render.
http://www.yiiframework.com/doc-2.0/yii-base-view.html#afterRender%28%29-detail
$this->view->on('afterRender', ...);
or globally set in app/config/main.php
return [
'components' => [
'view' => [
'on afterRender' => function ($event) {
/** #var $event yii\base\ViewEvent */
},
],
],
];
In yii2 the the result of the render is returned to to the caller function..
this way
return $this->render('index', [
'model' => $model,
]);
otherwise is not showed ..
ther your code or not show the index page or not execute the sql command..
what do you are trying to do don't speed up the page load simple ( i think ) you try to do another think when the page is loading..

Resources