When collection->map returnes array then data in Collection raise error - laravel

In laravel 6 app I have collection defined as :
class PermissionCollection extends ResourceCollection
{
public static $wrap = 'permissions';
public function toArray($request)
{
return $this->collection->transform(function($permission){
return [
'id' => $permission->id,
'name' => $permission->name,
'is_checked' => !empty($permission->is_checked) ? $permission->is_checked : null,
'guard_name' => $permission->guard_name,
'created_at' => $permission->created_at,
];
});
}
}
I use it in a control, like :
$permissions = $user->permissions->all();
$userPermissionLabels= Permission
::get()
->map(function ($item) use($permissions) {
$is_checked= false;
foreach( $permissions as $nextPermission ) {
if($nextPermission->permission_id === $item->id) {
$is_checked= true;
break;
}
}
return [ 'id'=> $item->id, 'name'=> $item->name, 'is_checked' => $is_checked];
})
->all();
return (new PermissionCollection($userPermissionLabels));
and I got error :
Trying to get property 'id' of non-object
Looks like the reason is that collection->map returnes array of data, not objects.
If there is a way to fix it without creating new collection(using array) ?
MODIFIED :
I logged loging in my collection,
public function toArray($request)
{
return $this->collection->transform(function($permission){
\Log::info(' PermissionCollection $permission');
\Log::info($permission);
return [
'id' => $permission->id,
'name' => $permission->name,
'is_checked' => !empty($permission->is_checked) ? $permission->is_checked : null,
'guard_name' => $permission->guard_name,
'created_at' => $permission->created_at,
];
});
}
and I see in logs:
PermissionCollection $permission
array (
'id' => 1,
'name' => 'App admin',
'is_checked' => false,
)
local.ERROR: Trying to get property 'id' of non-object
The value is valid array, not null.
I mean I have already use this collenction in other part of the app, can I use it without creating a new one...

I think you get this error because you CollectionResource need to object of the Permission model, but in your case it is trying to get id from an array, after map function. Try to extend your model instead of returning an new array

Related

Attempt to read property post_id on int

I have a small response from db model, and i colud rebase it and response in route, but i see error.
My Controller:
class PostController extends Controller {
public function getLastRecord() {
$lastRec = Post::latest('created_at')->first();
$res = [];
$res = collect($lastRec)->map(function($record) {
return [
'id' => $record->post_id,
'rec_name' => $record->post_name,
'user' => $record->user_id,
];
})->toArray();
return $res;
}
}
I want that response will be array
['id': 1, 'rec_name': 'test_name', 'user': 1]
instead names from db
['post_id': 1, 'post_name': 'test_name', 'user_id': 1]
Error:
Attempt to read property "post_id" on int
When you collect() a single Record, then call ->map() (or other iterative methods), it loops over your Model's columns, not multiple Post records. You can solve this by wrapping $lastRec in an array, or using ->get() instead of ->first():
$lastRec = Post::latest('created_at')->first();
return collect([$lastRec])->map(function($record) {
return [
'id' => $record->post_id,
'rec_name' => $record->post_name,
'user' => $record->user_id,
];
})->toArray();
// OR
$lastRecs = Post::latest('created_at')->get();
return $lastRecs->map(function ($record) {
return [
'id' => $record->post_id,
'rec_name' => $record->post_name,
'user' => $record->user_id,
];
})->toArray();
Or, since this is a single record (using ->first() only ever returns 1 record), you don't need to collect() or map() at all:
$lastRec = Post::latest('created_at')->first();
return [
'id' => $lastRec->post_id,
'rec_name' => $lastRec->post_name,
'user' => $lastRec->user_id
];

Verify duplicate values (multi column unique) on the array in Laravel5.7

relate as below issue
Verify duplicate values on the array in Laravel5.7
I am add two fields to data base.
// database/migrations/UpdateUsersTable.php
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('staff_no' , 10);
$table->string('staff_code');
$table->unique(['staff_no', 'staff_code']);
});
}
I want to verify if multi column unique in my database or post array value is duplicate or not?
Here is my codes :
this is my Controller
UsersController
public function MassStore(MassStoreUserRequest $request)
{
$inputs = $request->get('users');
//mass store process
User::massStore($inputs);
return redirect()->route('admin.users.index');
}
and this is my POST data (post data($inputs) will send like as below) :
'users' => [
[
'name' => 'Ken Tse',
'email' => 'ken#gamil.com',
'password' => 'ken12ken34ken',
'staff_no' => '20191201CT',
'staff_code' => 'IT-1azz',
],
[
'name' => 'Tom Yeung',
'email' => 'tom#gamil.com',
'password' => 'tom2222gt',
'staff_no' => '20191201CT', // staff_no + staff_code is duplicate, so need trigger error
'staff_code' => 'IT-1azz',
],
]
MassStoreUserRequest
public function rules()
{
return [
'users' => ['required','array'],
'users.*.name' => ['required'],
'users.*.email' => ['required','unique:users','email', 'distinct'],
'users.*.password' => ['required','string','min:8'],
'users.*.staff_no' => ['required','size:10'],
'users.*.staff_code' => ['required','string']
// how to set verify duplicate values(staff_no,staff_code unique) in here?
];
}
You can use distinct validation rule. So your code will look like-
public function rules()
{
return [
'users' => ['required','array'],
'users.*.name' => ['required'],
'users.*.email' => ['required','unique:users','email', 'distinct'],
'users.*.password' => ['required','string','min:8'],
'users.*.staff_no' => ['required','size:10'],
'users.*.staff_code' => ['required','string', 'distinct']
];
}
Change
`'users.*.staff_code' => ['required','string']` line to
'users.*.staff_code' => ['required','string', Rule::exists('staff')->where(function ($query) {
//condition to check if staff_code and staff_no combination is unique
return $query->where('staff_code', $request->('your_key')['staff_code'])->where('staff_no', $request->('your_key')['staff_no']) ? false : true; // You may need to make a loop if you can not specify key
}),]
I solve this problem myself.
https://laravel.com/api/5.7/Illuminate/Foundation/Http/FormRequest.html#method_validationData
main point is overrides method validationData(),make value "staff_no_code" to validation data.
Here is my codes :
MassStoreUserRequest
public function rules()
{
$validate_func = function($attribute, $value, $fail) {
$user = User::where(DB::raw("CONCAT(staff_no,staff_code )", '=', $value))
->first();
if (!empty($user->id)) {
$fail(trans('validation.alreadyExists'));
}
};
return [
'users' => ['required','array'],
'users.*.name' => ['required'],
'users.*.email' => ['required','unique:users','email', 'distinct'],
'users.*.password' => ['required','string','min:8'],
'users.*.staff_no' => ['required','size:10'],
'users.*.staff_code' => ['required','string']
// 'distinct' check when working with arrays, the field under validation must not have any duplicate values.
// $validate_func check DB exist
'users.*.staff_no_code' => ['distinct',$validate_func]
];
}
//make value "staff_no_code" to validation data
protected function validationData()
{
$inputs = $this->input();
$datas = [];
foreach ($inputs as $input ) {
$input['staff_no_code'] = $input['staff_no'] . $input['staff_code'];
$datas[] = $input;
}
return $datas;
}

Exporting Excel getting this error Trying to get property 'id' of non-object

I'm using Maatwebsite Laravel Excel package 3.0.
This is my InvoicesExport.php
class InvoicesExport implements FromCollection
{
public function collection()
{
$company_id = Auth::user()->company_id;
$assets = Asset::where('id', $company_id)->get()->toArray();
$assets_array = array();
if(!$assets->isEmpty()){
foreach($assets as $asset){
$assets_array[] = array(
'Asset ID' => $asset->id,
'Asset Name' => $asset->name,
'Description' => $asset->description,
'Serial Number' => $asset->serialno,
'External ID' => $asset->external_id,
'Location' => $asset->location,
'Expiry Date' => $asset->expiry_date,
'Owner' => $asset->owner,
'Status' => $asset->status,
'Updated at' => $asset->updated_at
);
}
}
//dd($assets_array);
return $assets_array;
}
}
And i keep getting this error
Trying to get property 'id' of non-object
And this is my function in controller
public function excel()
{
return Excel::download(new InvoicesExport, 'invoices.xlsx');
}
My code looks like this now and I keep getting this error.
Call to a member function each() on array
When i use dd($assets_array) I get those 2 items that i have in database, so i think maybe it's problem in my RETURN
It seems, the problem is outside of the InvoicesExport Class.
Why don't you change the type of return?
instead of returning
return $assets_array;
Do it like this:
return collect($assets_array);
you convert the collection to array and try to access it as object
just remove the toArray
$assets = Asset::where('id', $company_id)->get();

Sort yii2 gridview by column that's not in a model

I have Gridview and one column value I get via http request. Is there a way to sort the table by this column?
myTableModel.php
class myTableModel extends \yii\db\ActiveRecord
{
...,
public function getExternalValue() {
$client = new Client();
return $client->createRequest()->setMethod('get')
->setUrl('http:://...')->setData(['id' => 1])->send()->content;
}
}
myTableModelSearch.php
class myTableModelSearch extends myTableModel
{
public function rules()
{
return [
[[...,'externalValue'], 'string'],
[[..., 'externalValue'], 'safe']
];
}
public $externalValue;
public function searchView($params) {
$query = SomeTable::find();
$dataProvider = new ActiveDataProvider(['query' => $query]);
$dataProvider->setSort(['attributes' => [
'externalValue' => [
'asc' => ['externalValue' => SORT_ASC],
'desc' => ['externalValue' => SORT_DESC]
]
]]);
if (!($this->load($params) && $this->validate()))
return $dataProvider;
return $dataProvider;
}
}
view.php
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
... ,
[
'attribute' => 'externalValue',
'value' => function($item) {
return $item->externalValue;
},
]
],
]);
I also tried to add value to view simply with $item->getExternalValue() (and without public property set), but it makes no difference - when trying to sort I get database exception error SQLSTATE[42S22]: Column not found: 1054 Unknown column 'externalValue' in 'order clause'. How could I trick gridview, to make it sort my table by externalValue column?
You're using yii\data\ActiveDataProvider which uses an instance of ActiveQuery to find its data.
Try using yii\data\ArrayDataProvider, or extend yii\data\ActiveDataProvider to allow a second source for your data.
Additionally, you have to implement a sort function that can sort using your attribute.
see more here and here

Laravel putting the return of a trait array into the controller

I'm currently struggling with how to return a variables from a trait and it should be returned in the array to be used in the controller:
Trait:
public function getAllData($search)
{
if ($search->search == null) {
$search->search = '#technology';
}
$cb = new Codebird();
$cb->setConsumerKey(env('TwitterKey'), env('TwitterSecret'));
$cb->setToken(env('AccessToken'), env('AccessTokenSecret'));
//https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline
//https://dev.twitter.com/docs/api/1.1/get/search/tweets
$params = [
'q' => $search->search,
'lang' => 'en',
'count' => '5',
];
$reply = (array)$cb->search_tweets($params);
$data = (array)$reply['statuses'];
$s = count($reply['statuses']);
return [
'data' => $data,
's' => $s,
];
Controller:
public function TwitterData(Request $search) {
$data = $this->getAllData($search);
return view('front.search', compact('data'));
}
It currently gives me an error saying about using the object however I can't access the 'data' in the array
Error:
Trying to get property of non-object (View: C:\xampp\htdocs\TwitterProject\resources\views\front\search.blade.php)
You are returning an array on your getAllData method, but you are probably trying to access it as an object on your View:
WRONG:
{!! $data->data !!}
RIGHT:
{!! $data['data'] !!}

Resources