We have specific columns in tables having a status, these are abbreviations, we want these short words beeing replaced by full words.
for example:
E => Error
R => Running
D => Done
I already seen things as Laravel Translation, but this is not what we need I suppose? This is not a language translation.
Looking for something where I can set the full words of each abbreviation, and show these full words in blade like:
#get_full_word(column_name)
which will output the full name
I think it is a best case for Mutators.
class Test extends Model
{
protected $fullStatus = [
'E' => 'Error',
'R' => 'Running',
'D' => 'Done',
];
public function getFullStatusAttribute()
{
return $this->fullStatus[
$this->status
];
}
}
And of course if its in many Classes, it would be nice to create a Trait that holds the code.
You can create your own blade directive.
Blade::directive('abbreviation', function ($abbreviation) {
return "<?php echo Abbreviation::get($abbreviation); ?>";
});
where Abbreviation is your class with abbreviations, like this
class Abbreviation
{
private $abbreviations = [
'E' => 'Error'
'R' => 'Running'
'D' => 'Done'
];
public static function get($abbreviation)
{
return $abbreviations[$abbreviation];
}
}
Than you can use it in your blade #abbreviation('D')
Related
I exported a csv file with laravel-excel 3.1 and when reviewing the values are enclosed in quotes, so they are exported as strings, but I need it to be in type number
Exported csv file:
"ano_plantacion","zona","sitio","manejo","sup_ha","codigo","rpend"
"2018","87","3","10","30.69","2042201801",""
"2017","87","3","10","14.86","2042201701",""
What I want or should be:
ano_plantacion,zona,sitio,manejo,sup_ha,codigo,rpend
2018,87,3,10,30.69,2042201801,
2017,87,3,10,14.86,2042201701,
Class SuperImport:
<?php
namespace App\Exports;
use App\Super;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
class SuperExport implements FromCollection,WithHeadings, WithColumnFormatting
{
use Exportable;
protected $superficie;
public function __construct($superficie = null)
{
$this->superficie = $superficie;
}
public function headings(): array
{
return [
'ano_plantacion',
'zona',
'sitio',
'manejo',
'sup_ha',
'codigo',
'rpend',
];
}
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_GENERAL,
'B' => NumberFormat::FORMAT_GENERAL,
'C' => NumberFormat::FORMAT_GENERAL,
'D' => NumberFormat::FORMAT_GENERAL,
'E' => NumberFormat::FORMAT_GENERAL,
'F' => NumberFormat::FORMAT_GENERAL,
'G' => NumberFormat::FORMAT_GENERAL,
];
}
/**
* #return \Illuminate\Support\Collection
*/
public function collection()
{
return $this->superficie ?: Super::all();
}
}
Controller:
$super = Super::select('ano_plantacion','zona','sitio', 'manejo','sup_ha','codigo','rpend')->get();
Excel::store( new SuperExport($super), 'export/Super.csv' );
It is assumed that with the columnFormats() method it is possible to change the format, but I don't see in the documentation what format is available, and when executing the code the problem continues.
Help pls :(
I found another solution, instead of using laravel excel, I tried another library: https://github.com/rap2hpoutre/fast-excel
So was my controller:
(new FastExcel(Super::all()))->export(storage_path('app/export/SuperFast.csv'), function ($super) {
return [
'ano_plantacion' => $super->ano_plantacion,
'zona' => $super->zona,
'sitio' => $super->sitio,
'manejo' => $super->manejo,
'sup_ha' => $super->sup_ha,
'codigo' => $super->codigo,
'repend' => $super->repend,
];
});
This is how my csv was: http://prntscr.com/squjh5
My problem is, the api resource loading which i really not needed.
Look into my Api Resource files
//BoxItemResource.php
public function toArray($request)
{
return [
'box_id'=> $this->box_id,
'item_id'=> $this->item_id,
'item'=> new ItemResource($this->item)
];
}
//ItemResource.php
public function toArray($request)
{
return [
'id' => $this->id,
'shipping_price' => $this->shipping_price,
'condition_id' => $this->condition_id,
'condition' => new ConditionResource($this->condition)
];
}
//ConditionResource.php
public function toArray($request)
{
return [
'id'=> $this->id,
'name'=> $this->name
];
}
//controller
return BoxItemResource::collection(
BoxItem::with([
'item'
])->paginate(1)
);
My problem is, I just need only BoxItem and Item here. I don't really want to load condition.
If i remove the condition relation from ItemResource.php, it will work. but the problem is I am using the ItemResource.php in some other place which need this condition.
Is it possible to deny loading condition relation ship here.
more clearly, I want to load the relationship which I mention in controller(in ->with()) .
Thanks in advance.
API resources allow for conditional attribtues and conditional relationships.
For attributes, which in my opinion is sufficient to use in your case, this means you can simply wrap the attribute value in $this->when($condition, $value) and the whole attribute will be removed from the result if $condition == false. So a concrete example of your code:
return [
'box_id'=> $this->box_id,
'item_id'=> $this->item_id,
'item'=> $this->when($this->relationLoaded('item'), new ItemResource($this->item))
];
Or if you prefer using the relationship style:
return [
'box_id'=> $this->box_id,
'item_id'=> $this->item_id,
'item'=> new ItemResource($this->whenLoaded('item'))
];
Maybe you are looking for Conditional Relationships?
Ideally, it should look like the following:
public function toArray($request)
{
return [
'box_id'=> $this->box_id,
'item' => ItemResource::collection($this->whenLoaded('item'))
];
}
The item key will only be present if the relationship has been loaded.
I want to add models from one table called "modellist" in middle of the program.
foreach ($trans_infos as $key => $trans_info) {
if($trans_info->heirarchy_type==1 || $trans_info->heirarchy_type==2){
$model=TransactionModules::where('id',$info->module_id)->first();
$model_name=$model->model; // here am getting model name form table
use App\Models\.$model_name; //i used this function to include model on middle of program
$model_name::find($info->transaction_id)->update(['status' => 7]);
}
}
I have not tested this but try:
foreach ($trans_infos as $key => $trans_info) {
if($trans_info->heirarchy_type==1 || $trans_info->heirarchy_type==2){
$model=TransactionModules::where('id',$info->module_id)->first();
($model::class)::find($info->transaction_id)->update(['status' => 7]);
}
}
The class method returns the namespace with model name
I hope this works
You can do this direct on eloquent.
no need to declare use first
remember to use namespace as a string => "App\Models\\"
foreach ($trans_infos as $key => $trans_info) {
if($trans_info->heirarchy_type==1 || $trans_info->heirarchy_type==2)
{
$model=TransactionModules::where('id',$info->module_id)->first();
"App\Models\\".$model->model::find($info->transaction_id)
->update(['status' => 7]);
}
}
We're building a portal to replace part of an existing application as step one, but the DB schema holds to absolutely no conventions. Aside from the lack of any constraints, indexes, etc the names of columns are not descriptive and not snake-cased.
Is it possible to map DB table column names so that the portal uses proper descriptive and snake-cased column names like first_name but writes to the actual database column first to at least have the portal be a first step towards cleaning up the tech debt?
For example, similar to how the table name (Model::table) can be set if the table name doesn't follow convention:
Example
private $columns = [
// convention => actual
'first_name' => 'first',
'last_name' => 'last',
'mobile_phone' => 'phone',
'home_phone' => 'otherPhone', // seriously!?
];
I've looked through Model and the HasAttributes trait, but I'm still hoping that this might exist, or someone has found a way to do this as a temporary solution.
You can create a parent class for all your models:
abstract class Model extends \Illuminate\Database\Eloquent\Model {
protected $columns = [];
public function attributesToArray()
{
$attributes = parent::attributesToArray();
foreach ($this->columns as $convention => $actual) {
if (array_key_exists($actual, $attributes)) {
$attributes[$convention] = $attributes[$actual];
unset($attributes[$actual]);
}
}
return $attributes;
}
public function getAttribute($key)
{
if (array_key_exists($key, $this->columns)) {
$key = $this->columns[$key];
}
return parent::getAttributeValue($key);
}
public function setAttribute($key, $value)
{
if (array_key_exists($key, $this->columns)) {
$key = $this->columns[$key];
}
return parent::setAttribute($key, $value);
}
}
Then override $columns in your models:
protected $columns = [
'first_name' => 'first',
'last_name' => 'last',
'mobile_phone' => 'phone',
'home_phone' => 'otherPhone',
];
The proper way is to use accessors and mutators.
Defining An Accessor
public function getFirstNameAttribute() {
return $this->first;
}
Then, you can access the value by $model->first_name.
Defining A Mutator
public function setFirstNameAttribute($value) {
$this->attributes['first'] = $value;
}
Then, you can mutate the value for example:
$model->first_name = 'first_name';
$model->save();
I have a radio button with two values (required field) based on that value one field is shown (there are two fields which are intially hidden, its shown based on value of radio button) which should be required. So I used conditional validation for the initially hidden fields.
This is my model code:
public function rules()
{
return [
[['receipt_no', 'date_of_payment', 'payment_method_id',
'total_amount'], 'required'],
['nonmember_name', 'required', 'whenClient' => function($model)
{
return $model->is_member == 2;
}, 'enableClientValidation' => false],
['member_id', 'required', 'whenClient' => function($model)
{
return $model->is_member == 1;
}, 'enableClientValidation' => false],
[['receipt_no', 'date_of_payment', 'payment_method_id',
'total_amount','is_member'], 'required','on' => 'receipt'],
];
}
I use a scenario receipt, is_member is the radio button field. If I select a value of 1 for is_member then field member_id is visible and it should be a required one. If is_member has a value 2 then nonmember_name is displayed and it should become a required field. With my code in model I managed to achieve it. But now other actions (saving a new row of data into model) using this model is having error
Array ( [nonmember_name] => Array ( [0] => Name cannot be blank. ) )
So my question is how can I make conditional validation specific to a scenario (I think that my error is due to required rule defined in conditional validation )
EDIT:
This is my radio button
<?= $form->field($model, 'is_member')->radioList(array('1'=>'Member',2=>'Non Member'))->label('Member or Not'); ?>
In rules
public function rules()
{
return [
[
'nonmember_name',
'required',
'when' => function ($model) {
return $model->is_member == 2;
},
'whenClient' => "function (attribute, value) {
return $('#id').val() == '2';
}"
]
];
}
I prefer to use functions inside the model's rules, which makes it a lot easier to work with in the future.
One thing to mention that a lot of answers don't mention, is that you MUST manually re-trigger the Yii2 client side validation!
$("#w0").yiiActiveForm("validateAttribute", "createuserform-trainer_id");
In my example below, there are 2 types of accounts: trainer and trainee. In my admin panel, the admin can create a new user. If they choose "trainer" there is nothing more to do. If they choose a "trainee", that "trainee" must be assigned a "trainer" to go under.
So in code terms:
If user role == trainee, trainer_id is required and show it's form input.
Else hide the trainer_id input and trainer_id will not be required.
Model rules:
public function rules()
{
return [
[
'trainer_id', 'required', 'when' => function ($model) {
return $model->role == 2;
}, 'whenClient' => "isUserTypeTraineeChosen"
],
];
}
View after your form:
<?php $this->registerJs('
function isUserTypeTraineeChosen (attribute, value) {
if ($("#createuserform-role").val() == 2) {
$(".field-createuserform-trainer_id").show();
} else {
$("#createuserform-trainer_id").val(null);
$(".field-createuserform-trainer_id").hide();
}
return ($("#createuserform-role").val() == 2) ? true : false;
};
jQuery( "#createuserform-role" ).change(function() {
$("#w0").yiiActiveForm("validateAttribute", "createuserform-trainer_id");
});
jQuery( "#createuserform-role" ).keyup(function() {
$("#w0").yiiActiveForm("validateAttribute", "createuserform-trainer_id");
});
'); ?>
Note: This is a dropdown list, so change and keyup both are necessary to accurately detect it's change statuses. If your not using a dropdown, then both may not be necessary.
I also have targeted the trainer_id input to be hidden by default using CSS, as the default user type is a trainer.