I have multiple resources and mostly resource content few fields that are same for all other resource and it's very difficult to modify all the resource in case I need to update/add key/value in the resource.
Is there any way that I can create one main resource that will contain all common fields and then call the main resource in my another resource and add few additional fields.
Here is my controller where I am calling CitizenFeedResource file.
if ($events->total()) {
return CitizenFeedResource::collection($events);
}
This is my CitizenFeedResource file.
use Illuminate\Http\Resources\Json\JsonResource;
class CitizenFeedResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'start_timestamp' => optional($this->start_timestamp)->toDateTimeString(),
'end_timestamp' => optional($this->end_timestamp)->toDateTimeString(),
'location' => [
'name' => $this->location,
'landmark' => $this->landmark,
'coordinates' => $this->coordinates,
'city' => $this->city,
],
'open_event' => $this->open_event,
'full_day_event' => $this->full_day_event,
'banner' => $this->banner,
'url' => $this->path(),
'web_url' => $this->webUrl(),
'categories' => $this->categories,
'timestamp' => $this->created_at->toDateTimeString(),
'timestamp_ago' => $this->created_at->diffForHumans(),
'statistics' => $this->statistics,
'additional_details' => $this->additionalDetails(),
'municipal_details' => $this->municipal_details,
'user' => optional($this->user)->getProfile($this->channel, '1.1'),
'complaint_id' => $this->complaint_id,
'volunteers' => (isset($this->volunteers) && $this->volunteers) ? $this->user->getVolunteerProfile($this->volunteers, '1.1') : array(),
'share_count' => (isset($this->statistics) && isset($this->statistics['share_count'])) ? array_sum($this->statistics['share_count']) : 0,
'volunteer_status' => $this->getVolunteerStatus($request),
'editable' => $this->editable(),
'type' => 'Event',
];
}
}
You don't have to extend directly from JsonResponse, so you can create one main object let's say like this:
use Illuminate\Http\Resources\Json\JsonResource;
class BaseResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
];
}
}
and then
class CitizenFeedResource extends BaseResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
$data = parent::toArray($request);
$data['custom_field'] = $this->custom_field;
// ...
return $data;
}
}
Related
I tried to find a solution here but nothing worked. I want to return values from TagResource using MealResource because I have TagTranslations table and I'm getting the data from the table with translations in TagResource.
Relationships are correctly formed, meal and tag models are connected via meal_tags table and tagtranslations belongsTo Tag::class.
I used TagResource like this:
class TagResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$translation = $this->translations->where('tag_id', $this->id)->first();
return
[
'id' => $this->id,
'title' => $translation->title,
'slug' => $translation->slug,
];
}
}
and MealResource like this:
public function toArray($request)
{
$translation = $this->translations->where('meal_id', $this->id)->first();
$category_translation = $this->category->translations->where('category_id', $this->category->id)->first();
return [
'id' => $this->id,
'title' => $translation->title,
'decription' => $translation->description,
'category' => [
'id' => $this->category->id,
'title' => $category_translation->title,
'slug' => $category_translation->slug,
],
'tags' => FILL IN THE BLANK (have used TagResource:collection() and new TagResource()) and didnt work
];
}
public function toArray($request)
{
$translation = $this->translations->where('meal_id', $this->id)->first();
$category_translation = $this->category->translations->where('category_id', $this->category->id)->first();
return [
'id' => $this->id,
'title' => $translation->title,
'decription' => $translation->description,
'category' => [
'id' => $this->category->id,
'title' => $category_translation->title,
'slug' => $category_translation->slug,
],
'tags' => TagResource::collection($this->tags),
];
}
If all the Relationships namings/mappings are correct then this will work.And please make sure that model are perfectly mapped respectively.
I'm trying to customize the register of Laravel and I have this working but I need to add in some fields the last ID registered. In my actual code it registers all OK, but no login automatic after register.
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:ssn'],
'account' => ['required', 'string', 'max:255', 'unique:user_auth'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
$ssn1 = mt_rand(1000000,9999999);
$ssn2 = mt_rand(100000,999999);
$ssn = $ssn1 . $ssn2;
$user_auth = User::create([
'account' => $data['account'],
'password' => DB::raw("CONVERT(BINARY(16), ".l2off($data['password'])." )"),
'quiz1' => $data['quiz1'],
'quiz2' => $data['quiz2'],
'answer1' => DB::raw("CONVERT(BINARY(16), ".l2off($data['answer1'])." )"),
'answer2' => DB::raw("CONVERT(BINARY(16), ".l2off($data['answer2'])." )"),
]);
$userId = $user_auth->id;
$ssn_info = ssn::create([
'ssn' => $ssn,
'name' => $data['name'],
'email' => $data['email'],
'job' => $data['job'],
'phone' => $data['phone'],
'zip' => $data['zip'],
'addr_main' => $data['addr_main'],
'addr_etc' => $data['addr_etc'],
'account_num' => $user_auth->id,
]);
$user_info = user_info::create([
'account' => $data['account'],
'ssn' => $ssn,
'kind' => "99",
]);
$user_account = user_account::create([
'account' => $data['account'],
'pay_stat' => "1",
]);
}
}
but if change it one to
return User::create([
'account' => $data['account'],
'password' => DB::raw("CONVERT(BINARY(16), ".l2off($data['password'])." )"),
'quiz1' => $data['quiz1'],
'quiz2' => $data['quiz2'],
'answer1' => DB::raw("CONVERT(BINARY(16), ".l2off($data['answer1'])." )"),
'answer2' => DB::raw("CONVERT(BINARY(16), ".l2off($data['answer2'])." )"),
]);
It register and automatically logs in, but I don't understand the last ID in the follow sequences.
I solved this by adding return $user_auth; at the end.
I got the following error when I try to write $fillable in Model.
Illuminate\Database\QueryException SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect double value: 'required' for column db_productmanagementsystem.products.price at row 1 (SQL: insert into products (title, type, firstname, surname, price, papl, updated_at, created_at)
Model: Product.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = ['title', 'type', 'firstname', 'surname', 'price', 'papl'];
//use HasFactory;
}
ProductController.php
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$products=product::all();
return view('products', ['products'=>$products]);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('createProduct');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
request()->validate([
'title' => 'required',
'type' => 'required',
'firstname' => 'required',
'surname' => 'required',
'price' => 'required',
'papl' => 'required'
]);
Product::create([
'title' => 'required',
'type' => 'required',
'firstname' => 'required',
'surname' => 'required',
'price' => 'required',
'papl' => 'required'
]);
return redirect('/products');
}
/**
* Display the specified resource.
*
* #param \App\Models\Product $product
* #return \Illuminate\Http\Response
*/
public function show(Product $id)
{
return view('singleProduct', ['product'=>$id]);
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Models\Product $product
* #return \Illuminate\Http\Response
*/
public function edit(Product $id)
{
return view('editProduct', ['product'=>$id]);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Models\Product $product
* #return \Illuminate\Http\Response
*/
public function update($id)
{
request()->validate([
'title' => 'required',
'type' => 'required',
'firstname' => 'required',
'surname' => 'required',
'price' => 'required',
'papl' => 'required'
]);
$product=product::findOrFail($id);
$product->title = request('title');
$product->type = request('type');
$product->firstname = request('firstname');
$product->surname = request('surname');
$product->price = request('price');
$product->papl = request('papl');
$product->save();
return redirect('/products');
}
/**
* Remove the specified resource from storage.
*
* #param \App\Models\Product $product
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
$product=product::find($id)->delete();
return redirect('/products');
}
}
Database:
enter image description here
You didn't provide the right value to your product model.
Recheck your store method
Product::create([
'title' => 'required',
'type' => 'required',
'firstname' => 'required',
'surname' => 'required',
'price' => 'required', // here you passed a string. but this field type is double in the database schema
'papl' => 'required'
]);
you should get the Product values from the request:
Product::create([
'title' => $request->input( 'title'),
'type' => $request->input('type'),
'firstname' => $request->input('firstname'),
'surname' => $request->input('surname'),
'price' => $request->input('price'),
'papl' => $request->input('papl')
]);
How do i customize my Validation Messages in My REQUESTS FILE?
how do i add messages next to the rules?
What i want is to put customized messages just like the common validation. Is it possible? to do just the normal way of validation in the Requests?
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class ArticleRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => 'required|min:5',
'content' =>'required',
'user_id' => 'required|numeric',
'category_id' => 'required|numeric',
'published_at' => 'required|date'
];
}
}
You can define a messages() method with validation rules for that form request only:
class StoreArticleRequest extends Request
{
//
public function messages()
{
return [
'title.required' => 'The title is required.',
'category_id.numeric' => 'Invalid category value.',
];
}
}
It takes the form of the field name and the rule name, with a dot in between, i.e. field.rule.
You may customize the error messages used by the form request by
overriding the messages method. This method should return an array of
attribute / rule pairs and their corresponding error messages:
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
https://laravel.com/docs/5.3/validation#customizing-the-error-messages
I use this solution to translate the field labels:
...
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => 'required|min:5',
'content' =>'required',
'user_id' => 'required|numeric',
'category_id' => 'required|numeric',
'published_at' => 'required|date'
];
}
/**
* Get the validation attributes that apply to the request.
*
* #return array
*/
public function attributes()
{
return [
'title' => __('app.title'),
'content' => __('app.content'),
'user_id' => __('app.user'),
'category_id' => __('app.category'),
'published_at' => __('app.published_at')
];
}
I have table comments with column parent_id.
And this is content of CommentsTable.php:
namespace App\Model\Table;
use App\Model\Entity\Comment;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Comments Model
*/
class CommentsTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
$this->table('comments');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Posts', [
'foreignKey' => 'post_id',
'joinType' => 'INNER'
]);
$this->belongsTo('ParentComments', [
'className' => 'Comments',
'foreignKey' => 'parent_id'
]);
$this->hasMany('ChildComments', [
'className' => 'Comments',
'foreignKey' => 'parent_id'
]);
}
/**
* Default validation rules.
*
* #param \Cake\Validation\Validator $validator Validator instance.
* #return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->add('id', 'valid', ['rule' => 'numeric'])
->allowEmpty('id', 'create')
->requirePresence('body', 'create')
->notEmpty('body')
->requirePresence('path', 'create')
->notEmpty('path')
->add('status', 'valid', ['rule' => 'numeric'])
->requirePresence('status', 'create')
->notEmpty('status')
->add('created_at', 'valid', ['rule' => 'datetime'])
->requirePresence('created_at', 'create')
->notEmpty('created_at')
->add('updated_at', 'valid', ['rule' => 'datetime'])
->requirePresence('updated_at', 'create')
->notEmpty('updated_at');
return $validator;
}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* #param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* #return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['user_id'], 'Users'));
$rules->add($rules->existsIn(['post_id'], 'Posts'));
$rules->add($rules->existsIn(['parent_id'], 'ParentComments'));
return $rules;
}
}
I want to build rule for field parent_id: exist in ParentComments or equal to 0.
Can you help me?
Thank you very much.
Rules are just callable functions or callable classes. The existsIn() function is just an alias for the ExistsIn class. We can use the to our advantage:
...
use Cake\ORM\Rule\ExistsIn;
class CommentsTable extends Table
{
...
public function buildRules(RulesChecker $rules)
{
...
$rules->add(
function ($entity, $options) {
$rule = new ExistsIn(['parent_id'], 'ParentComments');
return $entity->parent_id === 1 || $rule($entity, $options);
},
['errorField' => 'parent_id', 'message' => 'Wrong Parent']
);
return $rules;
}
}