I am using Laravel 5.8 and maatwebsite/excel 3.1 to export to Excel but got an error.
Call to undefined method Maatwebsite\Excel\Excel::create()
I have written export code in Controller and View
config/app.php
/*
* Package Service Providers...
*/
Maatwebsite\Excel\ExcelServiceProvider::class,
//Class Aliases
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
Controller
use Excel;
public function msisdnExport()
{
$msisdns = User::select(
"phone"
)
->get();
// Initialize the array which will be passed into the Excel
// generator.
$msisdnsArray = [];
// Define the Excel spreadsheet headers
$msisdnsArray[] = ['MSISDN'];
// Convert each member of the returned collection into an array,
// and append it to the payments array.
foreach ($msisdns as $msisdn) {
$msisdnsArray[] = $msisdn->toArray();
}
// Generate and return the spreadsheet
// Excel::create('MSISDN', function($excel) use ($msisdnsArray) {
Excel::download('MSISDN', function($excel) use ($msisdnsArray) {
// Set the spreadsheet title, creator, and description
$excel->setTitle('MSISDN');
$excel->setCreator('Developers')->setCompany('Cloud Africa');
$excel->setDescription('users msisdn file');
// Build the spreadsheet, passing in the payments array
$excel->sheet('sheet1', function($sheet) use ($msisdnsArray) {
$sheet->fromArray($msisdnsArray, null, 'A1', false, false);
});
})->download('xlsx');
}
View
<i class="fa fa-file-excel-o"></i> Excel
When I click on Excel in view, it suppose to export to excel but got this error.
Call to undefined method Maatwebsite\Excel\Excel::create()
The create method has been removed. You have to use one of the following:
Excel::download($yourExport);
Excel::store($yourExport);
As stated in the upgrade guide:
Excel::create() is removed and replaced by Excel::download/Excel::store($yourExport)
Source: https://docs.laravel-excel.com/3.1/getting-started/upgrade.html#upgrading-to-3-from-2-1
Related
What is the most simple way to store custom attributes such as page titles or other key value pairs that may be attached to a route?
For example, say I want to add my own metadata data to:
Route::get('/themetest', [MyController::class, 'list'])->name('themetest');
I thought I could add a route macro to save metadata to be retrieved later using an addMetadata method like
Route::get('/themetest', [MyController::class, 'list'])->name('themetest')->addMetadata('title' => 'Page Title');
Is that possible? Doesn't seem like it is.
Is there a standard way to store this type of info? Or, any practical way? I thought maybe I could store them using default(), but that could change the default parameters for a controller function.
You could use the 'action' array of the Route to store this information if you had to:
// In a Service Provider # boot
Illuminate\Routing\Route::macro('addMetaData', function ($key, $value) {
$this->action['meta'][$key] = $value;
return $this;
});
Illuminate\Routing\Route::macro('getMetaData', function ($key = null) {
return is_null($key)
? $this->getAction('meta')
: $this->getAction('meta.'. $key);
});
// Route definition
Route::get('/themetest', [MyController::class, 'list'])
->name('themetest')
->addMetaData('title', 'Page Title');
// Controller method (Route action)
public function list(Request $request)
{
dump($request->route()->getMetaData('title'));
}
I'm currently on a laravel 5.8 + vue.js 2 project and I want to be able to upload an array of files in a form so it can appear inside the form data and saved.
Inside my form there is a Vue component, made to display the intended files to upload:
<input
name="documents[0][files]"
accept="image/*,application/pdf"
type="hidden"
v-model="files"
>
It has file as its model:
data(){
return{
files: null,
types: {},
label: 'Seleccionar Archivo',
selected_file: null,
file_type_id: '',
file_types: null
}
},
Within methods, onSelectFile assigns the file to a data variable, then it's sent to addNewFile, so said value may come to file, the model:
onSelectFile(e){
if(!e.target.files.length) return;
this.selected_file = e.target.files[0];
this.addNewFile(this.selected_file);
e.target.value = null;
},
addNewFile(file){
this.files = file;
},
However, when it's time to save and store. The formData on File looks like this: Image
Action sends you to the store method in the controller, which sends you to the addPolicy function:
public function store(StorePolicy $request)
{
Policy::addPolicy($request->validated());
addPolicy does a DB transaction for all data (in this case I'll only show what it does to save the file):
public static function addPolicy(array $data)
{
DB::transaction(function () use($data) {
if ( isset($data['documents']) ) {
foreach($data['documents'] as $files){
$policy->documents()->create([
'file' => $files['files']->file('file')->store($policy->employee->urlFolderEmployee(), 'public'),
'file_name' => $files['files']->file('file')->getClientOriginalName()
]);
}
}
return $policy;
});
}
However, the lines of code above never save said file, because it's recognized as a String instead of (binary).
Whenever I want to getClientOriginalName() for example it displays the error:
Call to a member function getClientOriginalName() on string
I've also set the form to accept files:
{!! Form::open(
[
'route'=>['policy.store'] ,
'method'=>'POST',
'id' => 'form_register_new_policy_modal',
'data-prefix' => "{$register}",
'data-modal' => "register_policy_modal",
'files' => true
])
!!}
Is there any way to get the file inside of the input data as a file instead of a string?
I used Twig with Symfony and I really loved it. I now have a CodeIgniter project and I want to integrate Twig with it.
I installed the latest versions of CodeIgniter and Twig via Composer and and followed this tutorial but I believe the code in the tutorial is for CI v3.
Could anyone who has integrated Twig with CI v4 help me with the proper code please.
UPDATE
solution below!
Try this I hope it will help you
Install Composer and run the following command to get the latest version:
composer require "twig/twig:^3.0"
Then after installation add this line of code to the baseController initController method just after the parent::initController, just like the code below
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
class BaseController extends Controller
{
protected $helpers = [];
protected $twig;
// protected $helper = [];
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
$appPaths = new \Config\Paths();
$appViewPaths = $appPaths->viewDirectory;
$loader = new \Twig\Loader\FilesystemLoader($appViewPaths);
$this->twig = new \Twig\Environment($loader, [
'cache' => WRITEPATH.'/cache/twig',
]);
}
}
So with this now you can call the view files in other controllers extends to parent controller BaseController
e.g
namespace App\Controllers;
class Home extends BaseController
{
public function index ()
{
// To load a template from a Twig environment, call the load() method which returns a \Twig\TemplateWrapper instance:
$template = $this->twig->load('index.html');
// To render the template with some variables, call the render() method:
return $template->render(['the' => 'variables', 'go' => 'here']);
// The display() method is a shortcut to output the rendered template.
// OR You can also load and render the template in one fell swoop:
return $this->twig->render('index.html', ['the' => 'variables', 'go' => 'here']);
// If a template defines blocks, they can be rendered individually via the renderBlock() call:
return $template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']);
// Note any of them above will work
}
}
If you still want to use view() with twig like codeigniter 4 default view function you can modify the Common.php file in app directory
by adding this block of code below.
if (!function_exists('view'))
{
function view($tpl, $data = []) {
$appPaths = new \Config\Paths();
$appViewPaths = $appPaths->viewDirectory;
$loader = new \Twig\Loader\FilesystemLoader($appViewPaths);
$twig = new \Twig\Environment($loader, [
'cache' => WRITEPATH.'/cache/twig',
]);
if (!stripos($tpl, '.twig')) {
$tpl = $tpl . '.twig';
}
return $twig->render($tpl, $data);
}
}
Then in controller call it like this
return view('index', ['name' => 'Chibueze Agwu'])
Then in view file index.twig
<!DOCTYPE html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<h1>My Webpage</h1>
{{ name }}
</body>
</html>
This will output
My Webpage
Chibueze Agwu
I haven't test this code but I hope it will work. If not call my attentions.
In order to obey the the rule of DRY (DO NOT REPEAT YOURSELF), you can go ahead to improve the code I will do that later
I found the solution some time ago and I'm posting it in case some people stumble across the question.
First of all, all your controllers must extend BaseController; this controller is available by default when you install CodeIgniter 4.
Create a custom helper file and put in [project-name]/appstarter/app/Helpers.
IMPORTANT
the name of your helper must be [name]_helper.php or it will not work!
for example mine is called custom_helper.php
Create the following function in the custom helper you just created:
use Twig\Environment;
use Twig\Extension\DebugExtension;
use Twig\Loader\FilesystemLoader;
use Twig\TwigFilter;
if (!function_exists('twig_conf')) {
function twig_conf() {
// the follwing line of code is the only one needed to make Twig work
// the lines of code that follow are optional
$loader = new FilesystemLoader('Views', '../app/');
// to be able to use the 'dump' function in twig files
$twig = new Environment($loader, ['debug' => true]);
$twig->addExtension(new DebugExtension());
// twig lets you create custom filters
$filter = new TwigFilter('_base_url', function ($asset) {
return base_url() . '/' . $asset;
});
$twig->addFilter($filter);
return $twig;
}
}
NOTE
before creating any custom filter, make sure Twig doesn't already has one built-in.
Now in the BaseController you'll find an empty array called $helpers. You must put the name of your custom helper in it. Mine is called custom_helper.php; so the code looks like this for me:
protected $helpers = ['custom'];
Just below the array you'll find the constructor for BaseController and this is where the Twig library will be initialized; by calling the function you created in your custom helper:
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) {
parent::initController($request, $response, $logger);
$this->twig = twig_conf();
}
Now you are good to go! To render your twig files in any controller:
return $this->twig->render('twig_name', $dataArray);
Try this I hope it will help you.
Install Composer and run the following command to get the latest version:
composer require "twig/twig:^3.0"
I'm trying to add export functionalities to my Laravel app. I'd like to export db data into an excel spreadsheet. I'm using the Maatwebsite package.
I'm using Laravel 7.12 and 3.1.19 of the Maatwebsite package.
I'm getting the following error when trying to export the data:
Call to undefined method Maatwebsite\Excel\Excel::create()
I added the foloowing use statement to my controller:
use Maatwebsite\Excel\Facades\Excel;
And registered the followings in config/app.php
Maatwebsite\Excel\ExcelServiceProvider::class,
in providers and
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
in the aliases section
Here is my function from the controller file:
public function excel() {
$subscribers = DB::table('subscribers')->get()->toArray();
// Use this for excel spreadsheet header
$subscriber_array[] = array('Name', 'Email');
// Convert subscriber data from php object to array and store them under $subscriber_array
foreach($subscribers as $subscriber) {
$subscriber_array[] = array(
'Name' => $subscriber->name,
'Email' => $subscriber->email
);
}
// "Subscriber Data" will be the name of the generated excel file
Excel::create('Subscriber Data', function($excel) use ($subscriber_array) {
$excel->setTitle('Subscriber Data');
$excel->sheet('Subscriber Data', function($sheet) use ($subscriber_array) {
$sheet->fromArray($subscriber_array, null, 'A1', false, false);
});
})->download('xlsx');
}
Did you try this?
use Maatwebsite\Excel\Facades\Excel;
OR
use Excel
Am trying to adapt TDD on laravel, but am getting trouble to test controller which queries a collection of records and returns view with data when I run my test it returns an error message that trying to get the id of undefined property
// my test
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
class JobApplicationTest extends TestCase
{
use WithoutMiddleware;
/** #test */
public function user_can_see_all_open_positions()
{
// when user visit apply for a job page
$this->withoutExceptionHandling();
$response = $this->get(route('positions.open'));
$response->assertSuccessful();
$response->assertViewIs('positions.open.index');
$response->assertViewHas('positions');
}
}
// My controller
public function open(Request $request)
{
//TODO support additional filters & searches
//initialize query
$query = Position::query()->which()->are()->open();
//paginate query result
$positions = $query->paginate(config('app.defaults.pageSize'));
$data = [
'route_title' => 'Open Job Positions',
'route_description' => 'Available Job Positions',
'positions' => $positions,
];
return view('positions.open.index', $data);
}
so the problem is when I run text it looks view is returned with no data while view references data returned to the controller
error message when running test
1) Tests\Unit\JobApplicationTest::user_can_see_all_open_positions
ErrorException: Trying to get property 'id' of non-object (View:
/var/www/html/ipf-projects/niajiri/resources/views/pos
itions/open/index.blade.php)
<h3>
<a href="{{ route('positions.preview', [
'id' => $position->id,
'slug' => str_slug($position->title)
]) }}" class="text-navy">
{!! $position->title !!} - {!! $position->organization->name !!}
</a>
</h3>
Within 'positions.open.index' it is trying to access an id property on a non-object.
This could be because your $query does not return any Position objects (i.e. $data->positions returns an empty Collection)
When running unit tests it is likely that it is creating a temporary database (sqlite by default) which will not be populated with any data. Try adding some Positions in your test like so:
/** #test */
public function user_can_see_all_open_positions()
{
// Create Positions
Position::create([/* Some data here */]);
Position::create([/* Some data here */]);
// when user visit apply for a job page
$this->withoutExceptionHandling();
$response = $this->get(route('positions.open'));
$response->assertSuccessful();
$response->assertViewIs('positions.open.index');
$response->assertViewHas('positions');
}