PhpStorm No Usages for get Attribute - laravel

I'm using the latest version of PhpStorm (2022.3.1) and Laravel 9+. This is not a huge issue, but rather a major eyesore.
For some reason when I use a Model to create a custom Attribute like this:
public function getFormattedStartDateAttribute(): string
{
if (!$this->start_date) {
return 'TBD';
} else {
return $this->start_date->format('M. d, Y');
}
}
And use in the view like this or this:
Date {{ $event->formattedStartDate }}
Date {{ $event->formatted_start_date }}
PhpStorm still says the method has no usages?
Image:
Is there a way to fix this? I've tried reindexing my project. This is a new feature called Code Vision.

The issue is very easy to solve, you can use barryvdh/laravel-ide-helper and then run php artisan ide:model, that will go over the models and create a PHPDoc block (you can add options and create them in the same model file or in a new file where you only have this PHPDock blocks), and PHPStorm will read this doc block and know when you are calling attributeWhatever is what type.
It will add this in your case:
/**
* #property string $formattedStartDate
*/
This way, any IDE that is capable of understanding PHPDock blocks, will understand that when you do $class->formattedStartDate, you are refering to that one, and it is of type string.
BUT, no IDE (unless using a plugin that I am not aware of) will understand that getFormattedStartDateAttribute -> formattedStartDate, so you will still get no usages for getFormattedStartDateAttribute, but at least you can track formattedStartDate and do whatever you want with it.
One quick tip, if you are using Laravel 9+, please change that code from:
public function getFormattedStartDateAttribute(): string
{
if (!$this->start_date) {
return 'TBD';
} else {
return $this->start_date->format('M. d, Y');
}
}
To:
public function formattedStartDate(): \Illuminate\Database\Eloquent\Casts\Attribute
{
return Attribute::get(
function ($value, $attributes) {
if (! $attributes['start_date']) {
return 'TBD';
} else {
return $attributes['start_date']->format('M. d, Y');
}
}
);
}
Why? Because using getFormattedStartDateAttribute is the old way, Laravel 9+ made it easier, read about Accessors.
See that getXXXXAttribute and setXXXXAttribute is not even present on the documentation anymore.

Related

Why using “Reformat Code” functionality some methods are differently formatted?

In PhpStorm 2021.1 working with Laravel 9 I periodically use “Reformat Code” functionality with all content of the file selected.
But some methods of this file looks differently formatted :
public function setBannerId(int $value): self
{
$this->bannerId = $value;
return $this;
}
...
public
function setDescriptionSize(
int $value
): self {
$this->descriptionSize = $value;
return $this;
}
I dislike a way the second method is formatted. I want all methods to be formatted as the first method?
UPDATED :
“Reformat Code” tab https://prnt.sc/cxkkYQdcRPjd printscreen
Can it be done?

Using latestOfMany() in Laravel

If I have a model called Placement which can have many PlacementTqLimit and I want to get the latest one, I'm assuming I can use this.
public function latestLimit()
{
return $this->hasOne(PlacementTqLimit::class)->latestOfMany();
}
And then add a custom attribute to get the value
public function getLatestLimitValueAttribute()
{
if (empty($this->latestLimit())) {
return '100';
}
return $this->latestLimit()->value;
}
However, when I dump the $this->latestLimit() I'm getting a Illuminate\Database\Eloquent\Relations\HasOne... I'm sure I shouldn't have to call return $this->hasOne(PlacementTqLimit::class)->latestOfMany()->latest(). Am I doing something wrong here?
$this->latestLimit() will return hasOne that extend query builder.
If you want to get the latest of PlacementTqLimit model just use $this->latestLimit without () or you can also use $this->latestLimit()->first()
So, to get the latest value limit, example code is:
public function getLatestLimitValueAttribute()
{
if (!$this->latestLimit) {
return '100';
}
return $this->latestLimit->value;
}

How to used Tucker-Eric/EloquentFilter Laravel

good day, I am using Tucker-Eric/EloquentFilter Laravel.
I want to filter it by relationship using Models
I want to automate it, instead of using the following:
public function users($users)
{
// dd($users);
return $this->r('users', $users);
}
public function user($user)
{
// dd($user);
return $this->r('user', $user);
}
public function owner($owner)
{
// dd($owner);
return $this->r('owner', $owner);
}
I want to make it one function that based on the relationship
so that I want to add another relationship on the model I don't need anymore to add another function.
Thanks!
We specifically stayed away from the type of implicit functionality you're looking for and opted for explicit filter methods to avoid security issues if/when new relations/properties were added to a model they wouldn't implicitly be available to filter against.
With that, what you're looking for isn't recommended because of the security concerns above but it can still exist if you implement it.
It sounds like the setup method would be the best place to implement it since it would be called first every time ->filter() is called.
public function setup()
{
foreach($this->input() as $key => $val) {
if($this->getModel()->$key() instanceof \Illuminate\Database\Eloquent\Relations\Relation) {
// Your logic here
}
}
}

Laravel 5 How to follow DRY in my simple controller logic?

I have some simple logic in my Controller. But I often use it in other method. Here is an example.
In my controller.
public function method1()
{
if(isset(Auth::user()->showroom->name)){
$showroomName = Auth::user()->showroom->name;
}else{
$showroomName = "Belum Ada Izin";
}
return view('method1view', compact('showroomName'));
}
public function method2()
{
if(isset(Auth::user()->showroom->name)){
$showroomName = Auth::user()->showroom->name;
}else{
$showroomName = "Belum Ada Izin";
}
return view('method2view', compact('showroomName'));
}
... so on
How I can follow DRY principle in my case?
Any help will be appreciated.
Thanks in advance.
For cleaner and shorter syntax, use data_get helper:
data_get(Auth::user(), 'showroom.name', 'your default value');
This in most cases comes handy, but not always is the best way.
However, in your example it seems, that maybe in fact you'd like to simply share this variable across your views - use share or a View Composer described in the docs.
In your Showroom model you could include the following function:
public function getNameAttribute($value)
{
return isset($value) ? $value : 'Belum Ada Izin';
}
That's assuming you want that behavior everywhere showroom->name is used. If not, make the function getNameWithDefaultAttribute, check $this->name in the body, and reference it in the controller like Auth::user()->showroom->name_with_default

doctrine2 - use custom query getter

I'm using Symfony2 and Doctrine2. How would I go about using a different query for a get method? (poorly worded, let me explain)
i.e. I have an application entity, this has a one to many relation with Version
so in my application entity I have:
/**
* Get versions
*
* #return Doctrine\Common\Collections\Collection
*/
public function getVersions()
{
return $this->versions;
}
This is all good, however, how can I implement a method, such as
getCurrentVersion, where I perform a simple query, such as:
SELECT v.* FROM version WHERE application_id = 1 AND current = 1
and so in a twig template, I can do:
{% for application in applications %}
Name : {{ application.name }}
Current Version: {{ application.getCurrentVersion }}
{% endfor %}
Any help is much appreciated.
p.s. if i'm going about this wrong, please enlighten me.
Thanks.
EDIT: http://www.doctrine-project.org/docs/orm/2.1/en/reference/limitations-and-known-issues.html#join-columns-with-non-primary-keys Seriously?!
EDIT, I really don't want to do this, it is unnecessary and resourcefully wasteful:
public function getCurrentVersion
{
foreach($this->versions as $version)
{
if($version->current)
{
return $version;
}
}
}
Take a look into https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-associations.html#filtering-collections
I believe that's what you've been looking for.
First, you shouldn't touch the database from your entity. It's considered bad practice to inject an entity manager into a managed entity, and it has no way of knowing about the data layer otherwise.
To do what you're asking, you can use a custom entity repository with a getCurrentVersion method that takes an id or instance of the entity and runs the query on it:
// class Foo\Bundle\Repository\BarRepository
public function getCurrentVersion(MyClass $class)
{
$dql = 'SELECT v FROM Namespace\Of\Version\Class v WHERE v.application_id=:id AND current=1';
$query = $this->_em->createQuery($dql);
$query->setParameter('id', $class->getId());
$version = $query->execute();
return $version;
}
Note that if you're only expecting one version, you can use $query->getSingleResult(); instead of $query->execute();
However, it sounds like you're trying to do versioning/history on some of your classes, in which case, you should check out the Gedmo DoctrineExtensions and associated Symfony2 bundle; specifically, have a look at the Loggable behavioral extension, which handles versioning of your entities transparently.

Resources