Laravel - Method App\Http\Controllers\MsisdnController::export does not exist - laravel

I am trying to export to Excel in Laravel 5.8 using
"maatwebsite/excel": "^3.1"
but I got this error:
Method App\Http\Controllers\MsisdnController::export does not exist.
Exports
namespace App\Exports;
use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
class MsisdnExport implements FromCollection
{
/**
* #return \Illuminate\Support\Collection
*/
public function collection()
{
return User::all();
}
}
MsisdnController
use App\Exports\MsisdnExport;
use Maatwebsite\Excel\Facades\Excel;
class MsisdnController extends Controller
{
public function msisdnexport()
{
return Excel::download(new MsisdnExport, 'msisdn.xlsx');
}
}
Sidebar Nav
<li>List of MSISDNs </li>
route
Route::get('msisdnexport', 'MsisdnController#export')->name('msisdnexport');
View
<div class="col-xs-4">
{{ Form::submit('Search',['class'=>'btn btn-warning']) }}
<i class="fa fa-file-excel-o"></i> Excel
</div>
#foreach($msisdns as $key => $msisdn)
<tr>
<td>{{ ++$key }}</td>
<td>{{ $msisdn->phone }}</td>
</tr>
#endforeach
When I click on Excel Button, I expect it to export to Excel. But I got the error above.

Your route definition:
Route::get('msisdnexport', 'MsisdnController#export');
references a function export that doesn't exist. Your function is named msisdnexport in your controller.

Related

Livewire use one component in a multiple time to update input fields

I'm using AlpineJs and Livewire in an application. I'm new to livewire, Here I want to Update the post name which is showing from a component inside another component. To reuse those I have separated those also there have lots of other features with complex logic.
Problem
The post name isn't changing, Not even fire the wire:model.
#post.table
#foreach ($posts as $index => $post)
<tr>
<td> {{ Str::limit($post->name, 22) }}</td>
<td> {{ $post->description }}</td>
<td> {{ $post->date }}</td>
<td> {{ $post->amount }}</td>
</tr>
<template x-if="some_condition">
<tr>
<livewire:post.post-details :post="$post" :index="$index">
</tr>
</template>
#endforeach
//pagination here
#post.post-details
class PostDetails extends Component
{
protected $post;
public $index;
public function mount($post, $index)
{
$this->post = $post;
$this->index = $index;
}
public function render()
{
return view('livewire.post.post-details', [
'post' => $this->post,
]);
}
}
<div>
<livewire:post.post-name :post="$post" :index="$index">
// Other components are here
</div>
#post.post-name
class PostName extends Component
{
public $post_name;
public $index;
protected $rules = [
'update_post.*.name' => 'required|string',
];
public function mount($schedule_entry, $index)
{
$this->post_name = $post->name;
$this->index = $index;
}
public function render()
{
return view('livewire.post.post-name');
}
public function some_action()
{
//
}
}
<div>
<input type="text" wire:model="update_post.{{ $index }}.name" wire:keydown="some_action" value="{{ $post_name }}">
</div>
If you guys have any better idea to reuse those component feel free to share. Thanks
I have try this two way
https://laravel-livewire.com/docs/2.x/properties#binding-models
https://laracasts.com/discuss/channels/livewire/livewire-save-fields-with-same-name

How to access model function in view or blade file

I want to get interest amount which is multiple of amount and interest rate in a table "loan". I want to call the value from a table and used for display loan information.
I have tried using mutators in which case gives same error as mentioned below
Loan.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $fillable = ['amount', 'interest', 'status', 'member_id', 'loan_type_id', 'interest_type_id', 'loan_payment_type_id'];
public function getInterestAmountAttribute()
{
return $this->amount * $this->interest;
}
public function member()
{
return $this->belongsTo(Member::class, 'member_id', 'id');
}
}
loan.blade.php
<table class="table table-stripped">
<thead>
<tr>
<th>Loan Id</th>
<th>Amount</th>
<th>Interest</th>
<th>Interest Amount</th>
<th>Interest Type</th>
<th>Loan Type</th>
<th>Status</th>
<th>Payment Type</th>
<th>Member</th>
<th>Action</th>
</tr>
#foreach($loanData as $key=>$loan)
<tr>
<td>{{++$key}}</td>
<td>{{$loan->amount}}</td>
<td>{{$loan->interest}}</td>
<td>{{ $loan->interest_amount}}</td>
<td>{{$loan->interesttype->interest_type}}</td>
<td>{{$loan->loantype->loan_type}}</td>
<td align="center">
<span class="bg bg-primary" style="border-radius: 10px;padding:2px 5px">{{$loan->status}}</span>
<form action="{{route('update-loan-status')}}" method="post">
{{csrf_field()}}
<input type="hidden" name="criteria" value="{{$loan->id}}"/>
#if($loan->status== 1)
<button class="btn btn-success btn-xs" name="paid"><i class="fa fa-check"></i></button>
#endif
#if($loan->status== 0)
<button class="btn btn-danger btn-xs" name="unpaid"><i class="fa fa-close"></i></button>
#endif
</form>
</td>
<td>{{$loan->paymentmethod->method}}</td>
<td>{{$loan->member->name}}</td>
<td>
Delete
Edit
</td>
</tr>
#endforeach
</thead>
</table>
{{$loanData->links()}}
This gives the following error:
Method Illuminate\Database\Eloquent\Collection::links does not exist.
when I remove brackets
<td>{{$loan->getInterest}}</td>
the error is
App\Loan::getInterest must return a relationship instance.
LoanController.php
<?php
namespace App\Http\Controllers\Backend;
use App\Http\Controllers\Controller;
use App\Loan;
use App\Interest;
use App\LoanPaymentMethod;
use App\Member;
use App\Loantype;
use DB;
class LoanController extends Controller
{
protected $_backendPath = 'backend.';
protected $_pagePath = 'backend.pages.';
protected $_data = [];
public function index()
{
$loanData = Loan::orderBy('id', 'desc')->get();
$loanData = Loan::paginate(10);
$loanData = Loan::all();
$memberData = Member::all();
$loantypeData = Loantype::all();
$paymentmethodData = LoanPaymentMethod::all();
$interestData = Interest::all();
$this->_data['loanData'] = $loanData;
//$results = Loan::with('member')->get();
//$dat->loan = Loan::with('member')->get();
//$loan = Member::find($memberData)->loan;
return view($this->_pagePath . 'loan.loan', $this->_data);
//$userData = DB::table('members')->get();
//return view('home',compact('userData'));
}
}
Define your function as accessor in your Loan.php :
public function getGetInterestAttribute()
{
return $this->amount * $this->interest;
}
Now you can access it , like this :
<td>{{ $loan->get_interest }}</td>
The right way to call an Accessor,
public function getModifiedInterestAttribute() // first get then ModifiedInterest then Attribute
{
return $this->amount * $this->interest;
}
Then you can call the Accessor like below,
<td>{{$loan->modified_interest }}</td>
You can see this for more details : https://laravel.com/docs/5.8/eloquent-mutators#defining-an-accessor
You should append that variable in model data Like
class Loan extends Model
{
protected $appends = ['interest'];
}
Your accessor should like
public function getInterest()
{
return $this->amount * $this->interest;
}
Access in blade file as you use above
<td>{{$loan->interest}}</td>

Changing menus order by dragging - Laravel

In my custom CMS I have created CRUD menu and in the frontend I'm displaying it successfully.
Now I'm trying to find any solution to change order by dragging these menu items in the admin section, but still no luck. Does anyone knows how to achieve this with Laravel? Also I use third party Laravel translatable, so I'll explain in my following code:
Menu model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Dimsav\Translatable\Translatable;
class Menu extends Model
{
use Translatable;
public $translatedAttributes = ['title', 'url', 'status'];
}
MenuTranslation model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class MenuTranslation extends Model
{
//
}
create_menus_table migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateMenusTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('menus', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('menus');
}
}
create_menus_translations_table migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateMenuTranslationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('menu_translations', function (Blueprint $table) {
$table->increments('id');
$table->integer('menu_id')->unsigned();
$table->string('locale')->index();
// The actual fields to store the content of your entity. You can add whatever you need.
$table->string('title');
$table->string('url')->nullable();
$table->string('status');
$table->unique(['menu_id', 'locale']);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('menu_translations');
}
}
My view index menu:
#extends('layouts.admin')
#section('content')
#if(session()->has('success_message'))
<div class="alert alert-success">
{{ session()->get('success_message') }}
</div>
#endif
<h1>Users</h1>
<a class="btn btn-primary" href="{{ route('menus.create') }}">Create new menu</a>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Status</th>
<th>Created</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
#foreach($menus as $menu)
<tr>
<td>{{ $menu->id }}</td>
<td>{{ $menu->title }}</td>
<td>{{ $menu->status ? 'Active' : 'Disabled' }}</td>
<td>{{ $menu->created_at->diffForHumans() }}</td>
<td>
<a class="btn btn-primary btn-edit" href="{{ route('menus.edit' , $menu->id) }}">Edit</a>
<form action="{{ route('menus.destroy', $menu->id) }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<input type="submit" class="btn btn-danger btn-delete" value="Delete">
</form>
</td>
</tr>
#endforeach
</tbody>
</table>
#endsection
As you can see in the view menu index I'm displaying the created menu items. The key is to use some js and Ajax I guess and with dragging to change the id's in the menus table or to create a new column in the database (order).
So, the question again is: how can I drag these menu items and change order in the database by using Laravel?
Well, it is all not laravel specific question but here is the answer.
So, For the frontend part, you'll need to use a plugin for Drag and Drop. E.g. Sortable
Sortable plugin gives you all the events of drag and drop. So you can simply create a hidden field or just create a variable in the javascript and pass that sorted value in the POST request when click on save function.
Now, you will need to add that data in a table sorted by menu_id.
And by clicking on save order, you will send all the newly ordered elements with their respective id.
And on the backend side, you will just need to loop through and update those elements.
Like this:
foreach($newSort as $key => $value):
$menuTranslation = MenuTranslation::findOrFail($key);
$menuTranslation->update(['menu_id' => $value]);
#endforeach;
All the best.
I've finally solved the problem!
I'm using this plugin for Laravel:
https://github.com/boxfrommars/rutorika-sortable
It's great for sorting eloquent. With some tweaks, lot of reading and testing, now it works great. :)

Laravel view won't loop model even though it is populated

I'm creating a web based interface for my dovecot database.
I can get a list of all the virtual domains in the database and the number of emails and aliases easily enough.
But when I try to load a page to list the emails under a specific domain, it goes weird.
Three simple models:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class VirtualDomain extends Model
{
public function emails()
{
return $this->hasMany('App\VirtualUser', 'domain_id');
}
public function aliases()
{
return $this->hasMany('App\VirtualAlias', 'domain_id');
}
}
class VirtualUser extends Model
{
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
];
}
class VirtualAlias extends Model
{
//
}
My default controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\VirtualDomain;
use App\VirtualUser;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('home', [
'domains' => VirtualDomain::all(),
]);
}
public function domain($name)
{
$domain = VirtualDomain::where('name', $name)->first();
return view('domain', [
'domain' => $domain,
'emails' => VirtualUser::where('domain_id', $domain->id),
]);
}
}
and a couple of simple blades
home.blade.php
<p>
{{ $domains->count() }} domains
</p>
<table class="table-summary">
<thead>
<tr>
<th>name</th>
<th>emails</th>
<th>aliases</th>
<th class="table-summary-options">options</th>
</tr>
</thead>
<tbody>
#foreach ($domains as $domain)
<tr>
<td><a title="view emails for this domain" href="domain/{{ $domain->name }}">{{ $domain->name }}</a></td>
<td>{{ $domain->emails->count() }}</td>
<td>{{ $domain->aliases->count() }}</td>
<td class="table-summary-options"><a class="ui-action" title="remove this domain" href=""><img src="/img/ui/remove.png" alt="remove"></a></td>
</tr>
#endforeach
</tbody>
</table>
and domain.blade.php
<p>
<< - {{ $domain->name }} - {{ $emails->count() }} emails
</p>
<table class="table-summary">
<thead>
<tr>
<th>email</th>
<th class="table-summary-options">options</th>
</tr>
</thead>
<tbody>
#foreach ($emails as $email)
<tr>
<td><a title="view aliases for this domain" href="email/{{ $email->email }}">{{ $email->email }}</a></td>
<td class="table-summary-options"><a class="ui-action" title="remove this email" href=""><img src="/img/ui/remove.png" alt="remove"></a></td>
</tr>
#endforeach
</tbody>
</table>
The view outputs the correct number of emails under the domain with {{ $emails->count() }} - but the#foreach ($emails as $email)` does not loop.
When I modify the blade to simple use the emails from the domain variable ({{ $domain->emails->count() }} and #foreach ($domain->emails as $email)), I get the right count and the list is populated correctly.
What's making it go wrong when using the emails variable?
You have to make a small change for it to work
public function domain($name)
{
$domain = VirtualDomain::where('name', $name)->first();
return view('domain', [
'domain' => $domain,
'emails' => VirtualUser::where('domain_id', $domain->id)->get(),
]);
}
Without ->get() you will get a query builder instance while with get() will return a collection. In the foreach loop a collection can be iterated while a query builder instance can't be.
Hope this helps

Accessing and displaying pivot table data

Theory:
Users can attend many events and many events can be attended by many users. Therefore, I have two many-to-many relationships within my models, linking to a pivot table (event_user). On attending each event, I want to be able to access the pivot table data (event_user) to see if they're already attending.
event_user:
--id
--event_id
--user_id
For example, my seed data is:
user 1 attending both event 2 and 3. I want to be able to show this within a view.
The closest I have got is (logically):
public function index()
{
$id = Auth::user()->id;
$attending = myApp\Event::find($id)->event;
var_dump($attending); **But this var_dump returns NULL, but $id returns the correct ID.**
$events = myApp\Event::all();
$this->layout->content = View::make('events.index')->with('events', $events);
}
My aim is to disable the 'attend' button, on any event where they are already attending, only leaving the attend-able events available!
Any help would be hugely appreciated. Thank you in advance.
Any additional code which you may find necessary:
Events Model:
<?php
namespace myApp;
use Eloquent;
class Event extends Eloquent {
public function consultant()
{
return $this->belongsToMany('myApp\Consultant');
}
public function location()
{
return $this->belongsToMany('myApp\Location');
}
public function user()
{
return $this->belongsToMany('myApp\User');
}
}
User Model:
<?php
namespace myApp;
use Eloquent;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
public function event()
{
return $this->belongsToMany('Event');
}
public function practice()
{
return $this->belongToMany('Practice');
}
index.blade.php (showing the event list)
<div class="panel panel-success">
<!-- Default panel contents -->
<div class="panel-heading"><strong>Events</strong></div>
<!-- <div class="panel-body">
</div> -->
<!-- Table -->
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Date</th>
<th>Presenter</th>
<th>Location</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach($events as $event)
<tr>
<td>{{ $event->title }}</td>
<td>{{ date("j F Y", strtotime($event->date)) }}</td>
<td>{{ $event->consultant()->first()->title }} {{ $event->consultant()->first()->surname }}</td>
<td>{{ $event->location()->first()->address_1 }}</td>
<td><button type="button" class="btn btn-info">Attend</button></td>
</tr>
#endforeach
</tbody>
</table>
</div>
</table>
I think you're going about this the wrong way, that or I have misunderstood.
Firstly, you're trying to find an event with the same primary key as the currently authenticated user, which isn't correct, although it's an easy hole to fall down.
$id = Auth::user()->id;
$attending = myApp\Event::find($id)->event;
// equivalent of: SELECT * FROM `events` WHERE `id` = ?
Instead you'll want to do this
$id = Auth::user()->id;
$attending = myApp\Event::where('user_id', $id)->get();
// equivalent of: SELECT * FROM `events` WHERE `user_id` = ? (user_id insted of events.id)
That being said, surely the user events can be accessed by just calling the event property on the auth user?
$user = Auth::user();
$attending = $user->event;
To take this one step further, and make it so that you can check inside the foreach loop, you could advanced the above code to look like the following
$user = Auth::user();
$attending = $user->event->lists('id');
This will make an array of ids from the returned events that you need to assign to the view
$this->layout->content = View::make('events.index', array('events' => $events, 'attending' => $attending));
Now you can freely access it in your foreach
#foreach($events as $event)
<tr>
<td>{{ $event->title }}</td>
<td>{{ date("j F Y", strtotime($event->date)) }}</td>
<td>{{ $event->consultant()->first()->title }} {{ $event->consultant()->first()->surname }}</td>
<td>{{ $event->location()->first()->address_1 }}</td>
<td>
#if (!in_array($event->id, $attending))
<button type="button" class="btn btn-info">Attend</button>
#endif
</td>
</tr>
#endforeach
Also, seeing as Event is a reserved Alias (unless you've modified the config, which I wouldn't recommend), you'll want to specify the namespace in the relationship declaration within User
public function event()
{
return $this->belongsToMany('myApp\Event');
}
As a final point, it's not an issue as such, but in my own code I try to name relationships that have the potential to return multiple objects in the plural, so it would be public function events();.

Resources