I would like to create a UUID/GUID for a specific column in Laravel 5. So i am using the Library from Webpatser to get an UUID in Laravel5.
I would like to set this as default for a specific column, so i guess i should use attributes, or?
But when i use
protected $attributes = array('guid' => Uuid::generate(4)->string);
ill always get an error with:
syntax error, unexpected '(', expecting ')'
I am not sure, because the syntax looks fine and when ill try
protected $attributes = array('guid' => 'dsadasfasfsaf');
Everything works fine (guid is a varchar(36) field) - and
Uuid::generate(4)->string
returns a string.
Do i need anything else to create a default value for my model? Thanks in advance.
PHP can't parse non-trivial expressions in initializers.
You can do this:
class YourClass
{
protected $attributes;
function __construct()
{
$this->attributes = array('guid' => Uuid::generate(4)->string);
}
}
Or this by using the setter method:
class YourClass
{
protected $attributes;
public function setAttributes($attributes)
{
$this->attributes = $attributes;
}
}
$classInstance = new YourClass;
$classInstance->setAttributes(array('guid' => Uuid::generate(4)->string));
Related
this is my laravel custom accessor which I am appending using
protected $appends = [leave_balances];
public function getLeaveBalancesAttribute() {
// some code
}
I want to pass a parameter when I am calling this accessor like this
public function getLeaveBalancesAttribute($parameter) {
// use $parameter here
}
$payslip = Payslip::find(1);
\Log::debug($payslip->leave_balances("PARAMETER"));
I have searched and found that it is not possible. please can some one provide any solution to this I need to pass this parameter.
you dont append attribute unless you want it to act as an attribute,
you can just create a method since you are calling it like a method
in you Payslip model
public function leaveBalances( $params ) {
return $params
}
then you can use it like
$payslip = Payslip::find(1);
$payslip->leaveBalances("PARAMETER") // which output PARAMETER
If you declare an Attribute, you can only use it like this (following your example:
protected $appends = ['leave_balances'];
public function getLeaveBalancesAttribute()
{
return 'Hi!';
}
$payslip = Payslip::find(1);
$value = $payslip->leave_balances;
dd($value); // This will output string(Hi!)
What you (I think) want is setLeaveBalancesAttribute, so you can pass a value and do whatever you want with it:
public function setLeaveBalancesAttribute($parameter)
{
return $parameter.' Yes!';
}
$payslip = Payslip::find(1);
$payslip->leave_balances = 'It works!';
dd($payslip->leave_balances); // This will output string(It works! Yes!)
But, if you are using Laravel 9+, please do use the new way of defining attributes, it is better.
You can set the attribute $appends in the model where you have the accessor. Something like this:
protected $appends = ['the name of accessor'];
However, it will be in the most, I think in all, the responses or query you do with the model you declare it.
Another options is creating a single instance of the model using the ::find method. For example:
$model_instance = Model::find($id);
$attribute = $model_instance->attribute;
Here is the documentation reference: https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor
I am trying to remove some fields before they are validated.
Trying to attempt this inside prepareForValidation()
use Illuminate\Foundation\Http\FormRequest;
class VideoRequest extends ApiRequest
{
// ..code..
protected function prepareForValidation()
{
$this->merge([
'public' => $this->toBoolean($this->public),
'notify' => $this->toBoolean($this->notify),
]);
$video_id = $this->route('video_id');
if($this->isMethod('put') && Video::salesStarted($video_id)){
Log::info('removing sales');
// attempt 1
$this->except(['sales_start', 'tickets', 'price']);
// attempt 2
$this->request->remove('sales_start');
// attempt 3
$this->offsetUnset('sales_start');
}
if($this->isMethod('put') && Video::streamStarted($video_id)){
Log::info('removing streams');
// attempt 1
$this->except(['stream_start', 'stream_count', 'archive']);
// attempt 2
$this->request->remove('sales_start');
// attempt 3
$this->offsetUnset('sales_start');
}
$thumb = $this->uploadThumbnail($video_id);
if($thumb !== null){
$this->merge($thumb);
}
}
// ..code..
}
I made sure the code was entering inside the if statement, however the fields are not being removed.
Running $this->request->remove() and $this->except() have no effect.
If I add safe() it throws Call to a member function safe() on null.
I also tried to use unset() but nothing seems to work.
The rules for the dates are like so:
'sales_start' => 'sometimes|required|date|after:now|before:stream_start',
'stream_start' => 'sometimes|required|date|after:now',
but the $request->validated() returns the errors although it shouldn't be validating the deleted fields.
"sales_start": [
"The sales start must be a date after now."
],
"stream_start": [
"The stream start must be a date after now."
]
Why are the fields not being deleted?
Edit
As requested I added some code.
This is what ApiRequest looks like:
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
abstract class ApiRequest extends FormRequest
{
protected function failedValidation(Validator $validator): void
{
$response['data'] = [];
$response['api_status'] = 'ng';
$response['status_message'] = 'failed validation';
$response['errors'] = $validator->errors()->toArray();
throw new HttpResponseException(
response()->json( $response, 422 )
);
}
protected function toBoolean($booleable)
{
return filter_var($booleable, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
}
}
And the request is called from the controller like so:
public function update(VideoRequest $request, $video_id)
{
... some code ...
$validated = $request->validated();
... some code ...
}
so $this refers to the VideoRequest that extends FormRequest.
Can't find anything about deleting. But acording to Laravel docs you pick what keys you need from a request as follows:
$request->only(['username', 'password']);
// plug everything you need into the array.
$request->except(['username', 'password']);
//plug everything you don't need into the array
The latter is probably most useful to you.
Example:
Say I have the following keys: ['username', 'password', 'randomVal'];
$request->only(['username', 'password']);
// Output:
['username', 'password']
$request->except(['username', 'password']);
// Output:
['randomVal']
To remove (unset) a key from a Request before it goes to the Controller you can use offsetUnset()
inside your request:
protected function prepareForValidation()
{
$this->offsetUnset('sales_start');//same goes for the other key to remove...
}
This is a bit of an ugly answer.
Instead of modifying the request before the validation, I tried adding exclude when getting rules().
So something along these lines:
public function rules() {
$ex = $this->isMethod('put') && Video::salesStarted($video_id) ? 'exclude|' : '';
return [
'sales_start' => $ex.'sometimes|required|other_stuff',
];
}
Note that the validation 'exclude' only works if added first.
So this won't work:
'sometimes|required|other_stuff|exclude' //exclude is called last
I am still unable to find out why remove(), exclude(), offsetUnset() were not working, so this is not the right answer, but I hope it helps if someone is having the same issue.
Edit
Setting this as correct answer as I was unable to find an alternative solution/fix.
In laravel 9 app I want to add additive paramerer into Resource and looking at this
Laravel 5.6 - Pass additional parameters to API Resource?
branch I remade in app/Http/Resources/CurrencyResource.php :
<?php
namespace App\Http\Resources;
use App\Library\Services\DateFunctionalityServiceInterface;
use Illuminate\Http\Resources\Json\JsonResource;
use App;
use Illuminate\Support\Facades\File;
use Spatie\Image\Image;
use App\Http\Resources\MediaImageResource;
class CurrencyResource extends JsonResource
{
protected $show_default_image = false;
public function showDefaultImage($value){
$this->show_default_image = $value;
return $this;
}
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
*
* #return array
*/
public function toArray($request)
{
$dateFunctionality = App::make(DateFunctionalityServiceInterface::class);
$currencyImage = [];
$currencyMedia = $this->getFirstMedia(config('app.media_app_name'));
if ( ! empty($currencyMedia) and File::exists($currencyMedia->getPath())) {
$currencyImage['url'] = $currencyMedia->getUrl();
$imageInstance = Image::load($currencyMedia->getUrl());
$currencyImage['width'] = $imageInstance->getWidth();
$currencyImage['height'] = $imageInstance->getHeight();
$currencyImage['size'] = $currencyMedia->size;
$currencyImage['file_title'] = $currencyMedia->file_name;
}
else {
\Log::info( varDump($this->show_default_image, ' -1 $this->show_default_image::') );
$currencyImage['url'] = $this->show_default_image ? '/images/default-currency.jpg' : '';
}
// $currencyMedia = $currency->getFirstMedia(config('app.media_app_name'));
return [
'id' => $this->id,
'name' => $this->name,
...
and with code in control :
'currency' => (new CurrencyResource($currency))->showDefaultImage(false),
its work ok, but I got an error :
Method Illuminate\Support\Collection::showDefaultImage does not exist.
when I applyed this method for collection:
return (CurrencyResource::collection($currencies))->showDefaultImage(true);
But in link above there is a similar way :
UserResource::collection($users)->foo('bar');
What is wrong in my code and how that can be fixed ?
Thanks!
I wonder if there is a reason you can't use this approach: https://stackoverflow.com/a/51689732/8485567
Then you can simply use the request parameters to modify your response.
If you really want to get that example working in that way, it seems you are not following the example correctly.
You need to override the static collection method inside your CurrencyResource class:
public static function collection($resource){
return new CurrencyResourceCollection($resource);
}
You also need to create the CurrencyResourceCollection class and define the showDefaultImage method and $show_default_image property on that class as in the example you referred to.
Then you should be able to do:
CurrencyResource::collection($currencies)->showDefaultImage(true);
The reason the way you are doing it doesn't work is because you haven't defined the static collection method on your resource hence it's defaulting to the normal behavior of returning a default collection object as you can see in your error message.
I have a variable which holds the model name like so
$fooTableName = 'foo_defs';
$fooModel = 'FooDefs';
Now I would like to insert in the DB using that model like so
$fooModel::insert([..foo..array...]);
Throws an error
"message": "Parse error: syntax error, unexpected '$fooModel' (T_VARIABLE), expecting identifier (T_STRING)",
Is it possible to do something like that? or will I be forced to use
DB::table('fooTableName')->insert([...foo...array...]);
If I do it in the latter way, the timestamps in the table are wrong. The created_at column is null and the updated_at has the value
EDIT 1
$model = CustomHelper::getNameSpace($this->tableNames[$i]);
// $model => /var/www/html/erp/app/Models/sales/InvoiceDefs
$model::insert($this->tableCollections[$this->tableNames[$i]]);
Most of them said that, it was namespace issue, so I have corrected it, but still it is throw error like
"message": "Class '/var/www/html/erp/app/Models/sales/InvoiceDefs' not
found",
What you are doing wrong is using model name as string, you need to refactor your code as like below :
$fooModel = 'App\Models\FooDefs';
I have a same situation before and i have created the function to do this
function convertVariableToModelName($modelName='',$nameSpace='')
{
//if the given name space iin array the implode to string with \\
if (is_array($nameSpace))
{
$nameSpace = implode('\\', $nameSpace);
}
//by default laravel ships with name space App so while is $nameSpace is not passed considering the
// model namespace as App
if (empty($nameSpace) || is_null($nameSpace) || $nameSpace === "")
{
$modelNameWithNameSpace = "App".'\\'.$modelName;
}
//if you are using custom name space such as App\Models\Base\Country.php
//$namespce must be ['App','Models','Base']
if (is_array($nameSpace))
{
$modelNameWithNameSpace = $nameSpace.'\\'.$modelName;
}
//if you are passing Such as App in name space
elseif (!is_array($nameSpace) && !empty($nameSpace) && !is_null($nameSpace) && $nameSpace !== "")
{
$modelNameWithNameSpace = $nameSpace.'\\'.$modelName;
}
//if the class exist with current namespace convert to container instance.
if (class_exists($modelNameWithNameSpace))
{
// $currentModelWithNameSpace = Container::getInstance()->make($modelNameWithNameSpace);
// use Illuminate\Container\Container;
$currentModelWithNameSpace = app($modelNameWithNameSpace);
}
//else throw the class not found exception
else
{
throw new \Exception("Unable to find Model : $modelName With NameSpace $nameSpace", E_USER_ERROR);
}
return $currentModelWithNameSpace;
}
How To user it:
Arguments
First Argument => Name of the Model
Second Argument => Namespcce of the Model
For Example we have the model name as Post
$postModel = convertVariableToModelName('Post');
dd($postModel::all());
Will returns all the values in the posts table
But in Some Situation You Model Will in the
Custom Namespace such as App\Models\Admin\User
So this function is created to overcome that
$userModel = convertVariableToModelName('User',['App','Models','Admin']);
dd($userModel::all());
You are feel free to customize the function
Hope it helps
Try the below one,
$fooModel = new FooDefs();
and then you can do the following also,
$fooModel->column1 = $value1;
$fooModel->column2 = $value2;
$fooModel->column2 = $value2;
$fooModel->save();
or
$fooModel->save([
'column1' => $value1,
'column2' => $value2,
'column3' => $value3,
])
Edited answer
$path = 'my\project\path\to\Models';
$fooModel = app($path.'\FooDefs');
$fooModel::save([
'column1' => $value1,
'column2' => $value2,
'column3' => $value3,
])
dd($fooModel ::all());
Try my edited answer.
When you have the name of class stored as string you can call method on that class by using the php method call_user_func_array like this
$class_name = "FooDefs";
call_user_func_array(array($class_name, "insert"), $data);
$data is an Array of data which will be past to the called function as arguments.
Just for simple advice It's will be Good if you save in the $class_name variable the FQN Fully Qualified Name of the class which is the __NAMESPACE__ follow by the name of the class. For sample purpose FQN look like Illuminate\Support\Facades\DB which you can get when you save you use User::class I presume you have some User model. That will return the Fully Qualified Name of the User model will will be App\User in case of Laravel.
$requests = $post['request'] // posting the data from view page
$models = "app\models".'\\'.$requests //geting the model
$model = $models::findOne($referenceId) //fetching value from database
I am currently developing an application which uses the newest version of Symfony2. I have some problems validating a form which includes a file upload field.
My form code looks like that (shortened):
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Validator\Constraints\MinLength;
use Symfony\Component\Validator\Constraints\Collection;
class EventEditForm extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add("name", "text", array("required" => true));
//....
$builder->add("image", "file", array("property_path" => false, "required" => false));
}
public function getDefaultOptions(array $options)
{
$collectionConstraint = new \Symfony\Component\Validator\Constraints\Collection(array(
'image' => new \Symfony\Component\Validator\Constraints\Image()
));
$options["validation_constraint"] = $collectionConstraint;
return $options;
}
public function getName()
{
return 'editeventform';
}
}
As you can see here I want to ensure that the uploaded file is an image. I use the form like this:
$form = $this->createForm(new \Trancefans\AdminBundle\Form\EventEditForm(), $event);
But when running this code I get the following error:
Expected argument of type array or Traversable and ArrayAccess, object
given
I really don't know where my fault is. I did it exactly as described in the documentation. Can somebody help me? :-)
BTW: The image is not represented by the event entitiy, but every other field of the form is. I use doctrine.
Symfony\Component\Validator\Constraints\CollectionValidator requires that the data it's validating is an array or an object that implements ArrayAccess and Traversable.
Ensure that your class definition for the $event instance implements ArrayAccess and Traversable so when CollectionValidator::validate() is invoked it can access your values to validate them accordingly.