syntax error, unexpected ',', expecting ']' - laravel

I'm trying to add data into db with all first words as capital letter. But it's shows error syntax error.
unexpected ',', expecting ']',,,,,,,,,,,,,,,,,,,
Model
protected $fillable = [
'category_name',
'category_description',
'category_slug',
'category_image'
];
public function setFirstNameAttribute($value)
{
$this->attributes[
'category_name',
'category_description',
'category_slug',
'category_image'
] = strtoupper($value);
}

Your usage of setFirstNameAttribute($value) mutator function is wrong. Mustator is only for one attribute. So you have to create multiple mutators for every attribute.
Possible answer. If you want to mutate category_name.
public function setCategoryNameAttribute($value)
{
$this->category_name = strtoupper($value);
}
And if you want to mutate category_description
public function setCategoryDescriptionAttribute($value)
{
$this->category_description = strtoupper($value);
}
likewise you need to define multiple mutators to all the other attributes.
EDIT
if you want to make only to capitalize the first letter of words use title_case() instead of strtoupper()
public function setCategoryDescriptionAttribute($value)
{
$this->category_description = title_case($value);
}

Try it.
public function setCategoryNameAttribute($value){
$this->attributes['category_name'] = strtoupper($value);
}
Or
public function setCategoryNameAttribute($value)
{
return strtoupper($value);
}
If you want to do with all field then you may have define the function for all.

$this->attributes[
'category_name',
'category_description',
'category_slug',
'category_image'
] = strtoupper($value);
You can't set multiple array values at once like this. You would have to set them separately or in a loop:
public function setFirstNameAttribute($value)
{
$attribute_names = [
'category_name',
'category_description',
'category_slug',
'category_image',
];
foreach ($attribute_names as $attribute_name) {
$this->attributes[$attribute_name] = strtoupper($value);
}
}

Related

Laravel / OctoberCMS frontend filter

I am using OctoberCMS and I have created a custom component. I am trying to create a frontend filter to filter Packages by the Tour they are assigned to.
This is what I have so far. The issue is that the code is looking for a tour field within the packages table rather than using the tour relationship. Does anyone have any ideas?
<?php namespace Jakefeeley\Sghsportingevents\Components;
use Cms\Classes\ComponentBase;
use JakeFeeley\SghSportingEvents\Models\Package;
use Illuminate\Support\Facades\Input;
class FilterPackages extends ComponentBase
{
public function componentDetails()
{
return [
'name' => 'Filter Packages',
'description' => 'Displays filters for packages'
];
}
public function onRun() {
$this->packages = $this->filterPackages();
}
protected function filterPackages() {
$tour = Input::get('tour');
$query = Package::all();
if($tour){
$query = Package::where('tour', '=', $tour)->get();
}
return $query;
}
public $packages;
}
I really appreciate any help you can provide.
Try to query the relationship when the filter input is provided.
This is one way to do it;
public $packages;
protected $tourCode;
public function init()
{
$this->tourCode = trim(post('tour', '')); // or input()
$this->packages = $this->loadPackages();
}
private function loadPackages()
{
$query = PackagesModel::query();
// Run your query only when the input 'tour' is present.
// This assumes the 'tours' db table has a column named 'code'
$query->when(!empty($this->tourCode), function ($q){
return $q->whereHas('tour', function ($qq) {
$qq->whereCode($this->tourCode);
});
});
return $query->get();
}
If you need to support pagination, sorting and any additional filters you can just add their properties like above. e.g;
protected $sortOrder;
public function defineProperties(): array
{
return [
'sortOrder' => [
'title' => 'Sort by',
'type' => 'dropdown',
'default' => 'id asc',
'options' => [...], // allowed sorting options
],
];
}
public function init()
{
$filters = (array) post();
$this->tourCode = isset($filters['tour']) ? trim($filters['tour']) : '';
$this->sortOrder = isset($filters['sortOrder']) ? $filters['sortOrder'] : $this->property('sortOrder');
$this->packages = $this->loadPackages();
}
If you have a more complex situation like ajax filter forms or dynamic partials then you can organize it in a way to load the records on demand vs on every request.e.g;
public function onRun()
{
$this->packages = $this->loadPackages();
}
public function onFilter()
{
if (request()->ajax()) {
try {
return [
"#target-container" => $this->renderPartial("#packages",
[
'packages' => $this->loadPackages()
]
),
];
} catch (Exception $ex) {
throw $ex;
}
}
return false;
}
// call component-name::onFilter from your partials..
You are looking for the whereHas method. You can find about here in the docs. I am not sure what your input is getting. This will also return a collection and not singular record. Use ->first() instead of ->get() if you are only expecting one result.
$package = Package::whereHas('tour', function ($query) {
$query->where('id', $tour);
})->get();

array must be compatible with Maatwebsite\Excel\Concerns\WithMapping::map($row) in - Laravel

I am using Laravel-5.8 and Maatwebsite-3.1 to export to excel.
<?php
namespace App\Exports;
use App\User;
use Auth;
class StudentExport implements FromCollection, ShouldAutoSize, WithHeadings, WithMappings, WithCustomStartCell
{
private $headings = [
'Student ID',
'Name',
'Class',
'Status',
'Teacher'
];
public function collection()
{
$current_terms = DB::table('appraisal_identity')->select('term_name')->where('company_id', $userCompany)->where('is_current', 1)->first()->term_name;
$publishedgoals = AppraisalGoal::select('employee_code')->where('is_published', 1)->where('company_id', $userCompany)->groupBy('employee_code')->get();
$published_goals = DB::table('hr_students AS e')
->join('hr_employees AS em','em.id','=','e.teacher_id')
->select(
'e.student_id',
DB::raw('CONCAT(e.first_name, " ", e.last_name) AS full_name'),
'e.student_class,
DB::raw('(CASE WHEN e.is_status = 3 THEN "Excellent" WHEN e.is_status = 2 THEN "Good" WHEN e.is_status = 1 THEN "Average" ELSE "Pass" END) AS student_status')
DB::raw('CONCAT(em.first_name, " ", em.last_name) AS teacher_name')
)
->whereIn('e.student_id', $publishedgoals)
->distinct()
->get();
$published_goals = $published_goals->unique('student_id');
return collect($published_goals, $current_terms);
}
public function map($published_goals, $current_terms): array
{
return [
$published_goals->student_id,
$published_goals->full_name,
$published_goals->student_class,
$published_goals->student_status,
$published_goals->teacher_name,
$current_terms->term_name,
];
}
public function startCell(): string
{
return 'A4';
}
public function headings() : array
{
return $this->headings;
}
public function registerEvents() : array
{
return [
AfterSheet::class => function(AfterSheet $event) {
$event->sheet->setCellValue('A2', 'Current Term:');
$event->sheet->getDelegate()->setCellValue('B2', $current_terms);
$cellRange = 'A4:E4'; // All headers
$event->sheet->getDelegate()->getStyle($cellRange)->getFont()->setSize(14);
$event->sheet->getDelegate()->getStyle($cellRange)->getFont()->getColor()
->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_WHITE);
$event->sheet->getDelegate()->getStyle($cellRange)->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB('FF17a2b8');
$event->sheet->setAutoFilter($cellRange);
},
];
}
}
This is my expected output:
I have written the code above to get this result:
I want to make B2 to have the output of this variable: $current_terms
I got this error:
ERROR: Declaration of App\Exports\HrEmployeeGoalExport::map($published_goals, $current_terms): array must be compatible with Maatwebsite\Excel\Concerns\WithMapping::map($row)
How do I resolve this?
Thank you
Check the install docs for Laravel excel: https://docs.laravel-excel.com/3.1/getting-started/installation.html#installation
You probably need to run…
composer require psr/simple-cache:2.0 maatwebsite/excel
Enjoy !
You are implementing a number of the contracts from the Maatwebsite\Excel package, one of those contracts specifies that you must implement a map method that takes a $row as the argument; Maatwebsite\Excel\Concerns\WithMapping::map($row).
In your class you have HrEmployeeGoalExport::map($published_goals, $current_terms): array
To get this to work, you must change your map function to be HrEmployeeGoalExport::map($row) and then use $row to do any mapping.'
As such, you need to change the arguments you are receiving and remove the return type that you have specified.

Laravel query to output json data as select list. How to amend existing code to concatenate two values

I've got a pre-existing function in my controller that will run a simple query and return the model_name and id then return the result as json.
public function getModel($id)
{
$models = DB::table('model')->where('man_id',$id)->pluck('model_name','id');
return json_encode($models);
}
New requirement is that I include an additional column named model_num with the query. Plan is to concatenate the model_name and model_num columns.
Tried the following, but it doesn't return any values and I get a 404 response for the json:
public function getModel($id)
{
$models = DB::table("model")->select("id","CONCAT(model_name, '-', model_num) as model")->where("man_id",$id)->pluck('model','id');
return json_encode($models);
}
Am I missing something obvious?
You are using SQL functions within a select these will probably not work. You can use selectRaw instead:
public function getModel($id)
{
$models = DB::table("model")
->selectRaw("id, CONCAT(model_name, '-', model_num) as model")
->where("man_id",$id)
->pluck('model','id');
return response()->json($models); // response()->json() is preferable
}
alternatively you can do the concatenating in the PHP side:
public function getModel($id)
{
$models = DB::table("model")
->select("id", "model_name" "model_num")
->where("man_id",$id)
->get()
->mapWithKeys(function ($model) {
return [ $model->id => $model->model_name.'-'.$model->model_num ];
})
return response()->json($models);
}
public function getModel($id)
{
$models = DB::table('model')->where('man_id',$id)->first() ;
$models->model = $models->model_name. '-'. $models->model_num;
return json_encode($models->pluck('model', 'id');
}

table relationship and how to use it in laravel controller

so, I have 2 tables, stage and event. Stage hasMany event, and Event belongsTo Stage. And I want to show all stage and its event as json. Here is my code in controller:
public function getschedule(){
$schedule = Stage::all();
//$event = Event_schedule2020::all();
if (!$schedule) {
return response()->json(['msg'=>'Error not found','code'=>'404']);
}
foreach($schedule->events as $array){
$datax[] = [
'id'=>$array->id,
'time'=>$array->time,
'category'=>$array->category,
'type'=>$array->title,
'designer'=>$array->designer,
];
}
foreach ($schedule as $item) {
$jadwal[] = [
'id'=>$item->id,
'date'=>$item->date,
'place'=>$item->stage,
'data'=>$datax,
];
}
return response()->json($jadwal);
}
but I always get this error
the error
so, is there anything I can do about this?
You can utilize inbuilt functions to do what you want to. Laravel automatically transforms model into JSON, no need to built arrays with it.
public function getschedule() {
// tell laravel you want to eager load events
$stages = Stage::with('events')->get();
// laravel knows you loaded events and therefor you can just return it and it does the rest automatically
return response()->json($stages);
}
in your Stage model you have to create relationship like this
public function events()
{
return $this->hasMany('App\Event');
}
then in your Controller
public function getschedule(){
$schedules = Stage::with('events')->get()->toArray();
return response()->json($schedules );
}
your mistake is call events on a collection for solve this you can change foreach like followings :
public function getschedule(){
$schedules = Stage::all(); // I add a 's' to $schedule because is better set plural name;
if (!$schedule) {
return response()->json(['msg'=>'Error not found','code'=>'404']);
}
foreach($schedules as $schedule){
$datax = [];
foreach($schedule->events as $event){
$datax[] = [
'id'=>$event->id,
'time'=>$event->time,
'category'=>$event->category,
'type'=>$event->title,
'designer'=>$event->designer,
];
}
$jadwal[] = [
'id'=>$item->id,
'date'=>$item->date,
'place'=>$item->stage,
'data'=>$datax,
];
}
return response()->json($jadwal);
}
but above solution is not recommended because send many request to server in any foreach loop, following solution is better:
public function getschedule(){
$schedules = Stage::with('events')->get(); // only this difference with above soloution and the rest is the same
if (!$schedule) {
return response()->json(['msg'=>'Error not found','code'=>'404']);
}
foreach($schedules as $schedule){
$datax = [];
foreach($schedule->events as $event){
$datax[] = [
'id'=>$event->id,
'time'=>$event->time,
'category'=>$event->category,
'type'=>$event->title,
'designer'=>$event->designer,
];
}
$jadwal[] = [
'id'=>$item->id,
'date'=>$item->date,
'place'=>$item->stage,
'data'=>$datax,
];
}
return response()->json($jadwal);
}

Adding custom eloquent attribute in Laravel 5

I have a function named siblings which fetches all siblings of a user.
select siblings(id) as `siblings` from users where id = 1
I can access the function in Eloquent as
User::where('id', 1)->first([DB::raw(siblings(id) as `siblings`)]->siblings;
I want to make the siblings available via custom attribute.
I added siblings to $appends array
I also created getSiblingsAttribute method in my User model as
public function getSiblingsAttribute()
{
if (!$this->exists()) {
return [];
}
$siblings = User::where('idd', $this->id)
->first([DB::raw('siblings(id) AS `siblings`')])
->siblings;
return explode(',', $siblings);
}
But this is not working as $this->id returns null
My table schema is users(id, username,...), so clearly id is present.
Is there a way by which I can bind the siblings function while querying db and then returning something like $this->siblings from getSiblingsAttribute. If I can bind siblings(id) as siblings with query select globally as we do for scopes using global scope.
That way my code can be simply
public function getSiblingsAttribute()
{
return $this->siblings;
}
The simplest way is to create a view in your database and use that as a table:
protected $table = 'user_view';
Otherwise I need more information about your id == null problem.
If you can fix this by your own in the next step it is important that you use an other column name by selecting as in your accessor otherwise you run in an infinite loop.
public function getSiblingsAttribute()
{
if (!$this->exists()) {
return [];
}
$siblings = User::where('id', $this->id)
->first([DB::raw('siblings(id) AS `siblings_value`')])
->siblings_value;
return explode(',', $siblings);
}
EDIT
Sadly there is no simple way to archieve this.
But after a little bit tinkering I have found a (not very nice) solution.
Give it a try.
You have to add the following class and trait to your app.
app/Classes/AdditionalColumnsTrait.php (additional column trait)
namespace App\Classes;
trait AdditionalColumnsTrait {
public function newEloquentBuilder($query) {
$builder = new EloquentBuilder($query);
$builder->additionalColumns = $this->getAdditionalColumns();
return $builder;
}
protected function getAdditionalColumns() {
return [];
}
}
app/Classes/EloquentBuilder.php (extended EloquentBuilder)
namespace App\Classes;
use Illuminate\Database\Eloquent\Builder;
class EloquentBuilder extends Builder {
public $additionalColumns = [];
public function getModels($columns = ['*']) {
$oldColumns = is_null($this->query->columns) ? [] : $this->query->columns;
$withTablePrefix = $this->getModel()->getTable() . '.*';
if (in_array('*', $columns) && !in_array($withTablePrefix, $oldColumns)) {
$this->query->addSelect(array_merge($columns, array_values($this->additionalColumns)));
} elseif (in_array($withTablePrefix, $oldColumns)) {
$this->query->addSelect(array_values($this->additionalColumns));
} else {
foreach ($this->additionalColumns as $name => $additionalColumn) {
if (!is_string($name)) {
$name = $additionalColumn;
}
if (in_array($name, $columns)) {
if (($key = array_search($name, $columns)) !== false) {
unset($columns[$key]);
}
$this->query->addSelect($additionalColumn);
}
}
if (is_null($oldColumns)) {
$this->query->addSelect($columns);
}
}
return parent::getModels($columns);
}
}
after that you can edit your model like this:
class User extends Model {
...
use App\Classes\AdditionalColumnsTrait;
protected function getAdditionalColumns() {
return [
'siblings' => DB::raw(siblings(id) as siblings)),
];
}
...
}
now your siblings column will be selected by default.
Also you have the option to select only specific columns.
If you don't want to select the additional columns you can use: User::find(['users.*']).
Perhaps it is a solution for you.

Resources