Call to a member function toArray() on array - php

I’m trying to use this package: https://packagist.org/packages/digital-creative/conditional-container. However with this basic example:
return array_merge(
[
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
/**
* Only show field Text::make('Field A') if the value of option is equals 1
*/
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1'),
Text::make('Title'),
Textarea::make('Description'),
],
$arr
);
I’m getting the error message: Call to a member function toArray() on array.
If I change to:
return array_merge(
[
[
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1')
],
It shows:
message: "Call to a member function getUpdateRules() on array"
even with only the example like below it shows "message: "Call to a member function toArray() on array":
public function definition(): array
{
return [
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1')
];
}
Do you know how to solve the issue? Thanks!

Not sure what is does, but you are sending an array to a class that class has a method toArray().
that's why i always use return types in my code cause it will break if the input does not match.
Could it be that it thinks that this is a collection or a class that needs to be inputted.
in some cases i am lazy and will try the following:
collect(return array_merge(
[
[
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1')
],)
because many packages uses Collection as a way to handle, filter and search an array.
but this is more a guess than actuall knowledge. Look at the function getUpdateRules() in the vendor map, what does it do.
/**
* #param Resource|Model $resource
*
* #return array
*/
public function resolveDependencyFieldUsingResource($resource): array
{
$matched = $this->runConditions(
$this->flattenRelationships($resource)
);
return $matched ? $this->fields->toArray() : [];
}
this is the function so as you can see it expects a model or resource class
according to the docs:
return [
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
//more suff
your return array
array_merge(
[ // <--- note the extra bracket
[
Select::make('Option', 'option')
->options([
1 => 'Option 1',
2 => 'Option 2',
3 => 'Option 3',
]),
ConditionalContainer::make([ Text::make('Field A') ])->if('option = 1')
],

Related

Formatting Excel Laravel with array data

I'm trying to write an excel from a laravel controller where i have all the data in an array, and i managed to write it, but i have to format it now, this is the array that i have:
[2020-12-30 13:22:05] local.DEBUG: array (
0 =>
array (
0 => '1',
1 => '2',
),
1 =>
array (
0 => 'Test Name 1',
1 => 'Test Name 2',
),
2 =>
array (
0 => 'user',
1 => 'user2',
),
3 =>
array (
0 => '1',
1 => '2',
),
)
This is the way i'm creating the Excel:
Excel::create('Filename', function($excel) use ($budgets) {
$excel->sheet('Sheetname', function($sheet) use ($budgets) { //$budgets is the array i'm printing on Log
$sheet->fromArray($budgets);
});
})->export('xls');
And this is the way that my excel is printing it:
1
2
Test Name 1
Test Name 2
user1
user2
1
2
And the way i want to print it is:
Code
Name
User
Number
1
Test Name 1
user1
1
2
Test Name 2
user2
2
But i don't know how to achieve this. Can anyone help me with this?
//edits//
I added some code to re estructure the array, now i have this:
$users = ['Code', 'Name', 'User', 'Number'];
for ($i=0; $i<count($code); $i++){
array_push($users, array($code[$i], $name[$i], $user[$i], $number[$i]));
}
Log::debug($users);
And this is the Log:
[2020-12-30 15:17:40] local.DEBUG: array (
0 => 'Code',
1 => 'Name',
2 => 'User',
3 => 'Number',
4 =>
array (
0 => '1',
1 => 'Test Name 1',
2 => 'user1',
3 => '1',
),
5 =>
array (
0 => '2',
1 => 'Test Name 2',
2 => 'user2',
3 => '2',
),
)
But i'm getting this error:
[message] => Row `Code` must be array.
[class] => PHPExcel_Exception
You will could re-structure your array.
To get the print you want array should look like:
$budget = [
['Code', 'Name', 'User', 'Number'],
[1, 'Test Name 1', 'user1', 1],
...
];
Ok, so, i managed to re-structure the array and getting the Excel the way i wanted doing this:
public function generateExcel(Request $request)
{
$code = $request->input('code');
$name = $request->input('name');
$user = $request->input('user');
$number = $request->input('number');
$users = array();
array_push($users, array('Code', 'Name', 'User', 'Number'));
for ($i=0; $i<count($code); $i++){
array_push($users, array($code[$i], $name[$i], $user[$i], $number[$i]));
}
Excel::create('Filename', function($excel) use ($users) {
$excel->sheet('Sheetname', function($sheet) use ($users) {
$sheet->fromArray($users);
});
})->export('xls');
return true;

How to insert with Eloquant a multi level entry?

Let's consider I have Quizzes that can contain Questions which each of them contains some Propositions. Therefore I have three models: Quiz, Question and Proposition. The propositions are linked to the questions through a pivot table that contains: id_question, id_proposition, is_correct.
In a Seeder, I would like to insert a dummy quiz which could be represented in YAML as follow:
title: A Quiz
questions:
- name: Animals
content: What's the difference between a duck?
propositions:
- text: The dog has two legs
is_correct: false
- text: One leg is both the same
is_correct: true
- text: Every duck has at least several teeth
is_correct: false
Traditionally in Laravel you need to split each step such as:
$quiz = new Quiz;
$quiz->name = "A Quiz";
$question = $quiz->questions()->create();
...
Is there a shorter way to hierarchically create a new entry that would look like this:
Quiz::create([
'name' => 'A Quiz'
'questions' => [
Question::Create([
'name' => 'Animals',
'content' => "What's the difference between a duck?"
'propositions' => [
Proposition::Create(['content' => 'The dog has two legs']),
Proposition::Create(['content' => 'One leg is both the same'])
Proposition::Create(['content' => 'Every duck has at least several teeth'])
]
])
]
]
just testing with static values :
$quiz = Quiz::create([
'name' => 'A quiz',
])->questions()->createMany([
['name' => 'animals', 'content' => 'animals content'],
['name' => 'fruits', 'content' => 'fruits content'],
])->map(function($value, $key){
$value->propositions()->createMany([
['content' => 'content 1'],
['content' => 'content 2'],
]);
});
i think you can set the values based on YAML index-values(something like json) with foreach

How do I remap my array keys using an array of integers?

Here is my original array of items
$items = [
0 => 'item 1',
1 => 'item 2',
2 => 'item 3'
];
I want to change the order of the items based on their keys, so I'm doing this...
$reorder = [2,0,1];
uksort($items, function($key1, $key2) use ($reorder) {
return (array_search($key1, $reorder) > array_search($key2, $reorder));
});
This works as it should, and produces the proper results.
$items = [
2 => 'item 3',
0 => 'item 1',
1 => 'item 2'
];
However, when returning that in Laravel as json the newly ordered $items reverts back to the original order, which is obviously not what I want.
Is there a way to remap the array keys while reordering them?
How exactly are you returning the array in Laravel? The following example works for me exactly as you want it.
Route::get('/test', function () {
$items = [
0 => 'item 1',
1 => 'item 2',
2 => 'item 3'
];
$reorder = [2,0,1];
uksort($items, function($key1, $key2) use ($reorder) {
return (array_search($key1, $reorder) > array_search($key2, $reorder));
});
return response()->json($items);
// {"2":"item 3","0":"item 1","1":"item 2"}
});
If you have tried it in a browser, keep in mind that some browsers automatically reorder json arrays. In that case you have to get the raw instead of the formatted data.

Calling PHP Class Public Function Inside Smarty Template

Can someone help me out here.
How can i Call a PHP class public function inside a Smarty template file for example.
I have 2 Functions inside the Movie Class
GetAllMovies(); // Gets all Movies
and
GetMovie($movie_id); // Gets movie by movie id
Now i am calling the GetAllMovies(); and assigning it to the template
<?php
include 'movie.class.php';
$movie = new Movie();
$movies = $movie->GetAllMovies();
$smarty->assign('movies',$movies);
<?
Now inside the template file i've got a foreach statement for the movies.
{foreach from=$movies key=key item=mov}
// Access Movie ID, Title And Images
{/foreach}
Now what i want to do is to call GetMovie($movie_id); inside this foreach statement for example do something like this.
Assign Movie class to Smarty Template.
$smarty->assign('movie',$movie);
Then use $movie to call the function for example
{foreach from=$movies key=key item=mov}
{assign var=movie_info value=$movie::GetMovie($mov.id)}
{$movie_info.rating}
{/foreach}
Could someone please point me in the right direction.
It looks realy creepy but if you realy want to use it in that way, I suggest to create array on PHP side and assing it to smarty like:
$movies = array();
$movie = new Movie();
foreach ($movie->GetAllMovies() as $key => $movieDetails) {
$mov = new Movie();
$movies[] = $mov->getMovie($movieDetails['id']);
}
$smarty->assign('movies',$movies);
and in smarty you can loop thrue your $movies array
{foreach from=$movies key=key item=mov}
{$mov.rating}
{/foreach}
Based on this:
http://www.smarty.net/docs/en/advanced.features.static.classes.tpl
This should work:
{assign var=movie_info value=Movie::GetMovie($mov.id)}
At least if it is an existing static method...
I wouldn't tell you how to do it because it doesn't make any sense for me.
Template engine is for displaying data and you should get data inside Model/Controller. You should assign to Smarty data that is prepared to display and in Smarty you should display it.
So in your case before:
$smarty->assign('movies',$movies);
you should use:
$movies = $movie->GetAllMovies();
foreach ($movies as $k => $v) {
$movies[$k]['details'] = $movie->GetMovie($v['id');
}
and then in Smarty:
{foreach from=$movies key=key item=mov}
{$mov.details.rating}
{/foreach}
However if I were you, I would consider getting data. I assume that you get your movies from Database, so using:
$movies = $movie->GetAllMovies(); // 1 query
foreach ($movies as $k => $v) {
$movies[$k]['details'] = $movie->GetMovie($v['id'); // n queries
}
you run n+1 queries to your database, where n is number of movies.
It's quite possible that instead of this, you could run one query to database (depending on your structure using join or even not) so you should rethink if you get data the best way it's possible.
I think the proper way to do it, would be pulling your movies data in a 'ready-to-display' form, such as an array, associative array or their multidimensional counterparts that smarty can handle right away with the {foreach} tag. Maybe something that looked like:
array (
0 => array ( 0 => 'PHP the Movie 1', 1 => '2009', 2 => 'Coder 1', 3 => '3', ),
1 => array ( 0 => 'PHP the Movie 2', 1 => '2010', 2 => 'Coder 2', 3 => '2', ),
2 => array ( 0 => 'PHP the Movie 3', 1 => '2011', 2 => 'Coder 3', 3 => '1', ),
)
array (
0 => array (
'title' => 'PHP the Movie 1',
'year' => '2009',
'director' => 'Coder 1',
'rating' => '3', ),
1 => array (
'title' => 'PHP the Movie 2',
'year' => '2010',
'director' => 'Coder 2',
'rating' => '2', ),
2 => array (
'title' => 'PHP the Movie 3',
'year' => '2011',
'director' => 'Coder 3',
'rating' => '1', ),
)
array (
0 => array (
'title' => 'PHP the Movie 1',
'year' => '2009',
'director' => 'Coder 1',
'rating' => '3', ),
1 => array (
'title' => 'PHP the Movie 2',
'year' => '2010',
'director' => 'Coder 2',
'rating' => '2', ),
2 => array (
'title' => 'PHP the Movie 3',
'year' => '2011',
'director' => 'Coder 3',
'rating' => '1', ),
)
Only my humble opinion but I actually use it at work both to display data-sets with smarty and to build JSON responses for AJAX requests to the server.
You could use static methods in your movie class.
If for example your class is named "MovieClass" then you could have:
MovieClass::GetMovie($mov.id);
To create a static method just use the following format when declaring the method inside your class
public static GetMovie($mov.id)
{
...
}

Creating a dropdown menu from an array and prepend the array

I have an array which I will use for a dropdown in a form. My array is something like this...
$data = ('1' => 'Option 1', '2' => 'Option 2', '3' => 'Options 3')
Now I want to prepend this to the $data array
'' => 'Please select'
How do I do this? I've tried array_unshift but this adds a key to my option which I don't want because of my form validation.
Anyone help?
Thanks
All array values have a key. array_shift is the best way to do this.
You can use union operator
$data = ('1' => 'Option 1', '2' => 'Option 2', '3' => 'Options 3')
$prependArray = array('' => 'Please select');
$result = $prependArray + $data;

Categories