I have a application that I am trying to add a second Module to.
Basically i'm cloning an existing module that is already working with my database. All code is exactly the same as the original/working module, other than a different table name and different controller/class/model names.
I have 3 new tables that are related to the new module, just like with the old module investments, investment_categories and investment_vendors.
Every time I try to use my new module it wants to upload the vendor and category name value to the investments table when it should be uploading that to the respective investment_categories and investment_vendor tables.
I don't believe the issue is with my new module code, but somewhere else within composer.
I don't expect that I would need to run composer dump-autoload as I've always edited my modules without running that (but this is my first time updating one to query/write to a different table).
Is there something else I need to be running to get this to work?
The below error I see in the log is:
[2018-01-24 21:13:21] production.ERROR: PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'category_name' in 'field list' in /var/www//vendor/laravel/framework/src/Illuminate/Database/Connection.php:390
Controller File:
<?php
namespace MC\Modules\Investments\Controllers;
use MC\Http\Controllers\Controller;
use MC\Modules\Investments\Models\Investment;
use MC\Modules\Investments\Models\InvestmentCategory;
use MC\Modules\Investments\Models\InvestmentVendor;
class InvestmentController extends Controller
{
use ReturnUrl;
public function index()
{
$this->setReturnUrl();
$investments = Investment::defaultQuery()
->keywords(request('search'))
->categoryId(request('category'))
->vendorId(request('vendor'))
->sortable(['investment_date' => 'desc'])
->paginate(config('mc.defaultNumPerPage'));
return view('investments.index')
->with('investments', $investments)
->with('displaySearch', true)
->with('categories', ['' => trans('mc.all_categories')] + InvestmentCategory::getList())
->with('vendors', ['' => trans('mc.all_vendors')] + InvestmentVendor::getList())
}
Create Controller File:
<?php
namespace MC\Modules\Investments\Controllers;
use MC\Http\Controllers\Controller;
use MC\Modules\Investments\Models\Investment;
class InvestmentCreateController extends Controller
{
public function create()
{
return view('investments.form')
->with('editMode', false)
->with('currentDate', DateFormatter::format(date('Y-m-d')))
}
public function store()
{
$record = request()->except('attachments');
$record['investment_date'] = DateFormatter::unformat($record['investment_date']);
$record['amount'] = NumberFormatter::unformat($record['amount']);
$record['tax'] = ($record['tax']) ? NumberFormatter::unformat($record['tax']) : 0;
$investment = Investment::create($record);
return redirect($this->getReturnUrl())
->with('alertSuccess', trans('mc.record_successfully_created'));
}
}
Model:
<?php
namespace MC\Modules\Investments\Models;
use Illuminate\Database\Eloquent\Model;
class Investment extends Model
{
use Sortable;
protected $table = 'investments';
protected $guarded = ['id'];
protected $sortable = ['investment_date', 'investment_categories.name', 'description', 'amount'];
public static function boot()
{
parent::boot();
}
/*
|--------------------------------------------------------------------------
| Relationships
|--------------------------------------------------------------------------
*/
public function attachments()
{
return $this->morphMany('MC\Modules\Attachments\Models\Attachment', 'attachable');
}
public function category()
{
return $this->belongsTo('MC\Modules\Investments\Models\InvestmentCategory');
}
public function vendor()
{
return $this->belongsTo('MC\Modules\Investments\Models\InvestmentVendor');
}
/*
|--------------------------------------------------------------------------
| Accessors
|--------------------------------------------------------------------------
*/
public function getAttachmentPathAttribute()
{
return attachment_path('investments/' . $this->id);
}
public function getFormattedAmountAttribute()
{
return CurrencyFormatter::format($this->amount);
}
public function getFormattedTaxAttribute()
{
return CurrencyFormatter::format($this->tax);
}
public function getFormattedInvestmentDateAttribute()
{
return DateFormatter::format($this->investment_date);
}
/*
|--------------------------------------------------------------------------
| Scopes
|--------------------------------------------------------------------------
*/
public function scopeCategoryId($query, $categoryId = null)
{
if ($categoryId)
{
$query->where('category_id', $categoryId);
}
return $query;
}
public function scopeDefaultQuery($query)
{
return $query->select('investments.*', 'investment_categories.name AS category_name',
'investment_vendors.name AS vendor_name', 'clients.unique_name AS client_name')
->join('investment_categories', 'investment_categories.id', '=', 'investments.category_id')
->leftJoin('investment_vendors', 'investment_vendors.id', '=', 'investments.vendor_id');
}
public function scopeVendorId($query, $vendorId = null)
{
if ($vendorId)
{
$query->where('vendor_id', $vendorId);
}
return $query;
}
}
One thing to note is that I do have existing data in the table and the query works fine when viewing it from my web page, however the issue is when trying to edit it or insert new data/record.
As you can see from the model above,
investments.*', 'investment_categories.name AS category_name
the query works because of that command.
I cannot find anywhere else where it determines how to take "investment_categories.name as category_name".
Can you tell me why it is trying to write the category_name value to the investments table instead of the investment_categories table's name column?
Related
I have been trying to figure out how to implement a matching system but have become stuck.
I've managed to build a query within a controller which does exactly the same thing as I want it to do, but I would like to convert it to an Eloquent Model since images are broken and also can access some functions inside my Model.
Here's the query builder within the controller that I wish to convert (if it's possible at all)- I am checking if users have both "liked" each other (similar to Tinder):
class MatchedEmployersController extends Controller
{
public function index()
{
$matches = DB::table('applicant_likes')
->join('employers', 'employers.id', '=', 'applicant_likes.liked_employer_id')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('employer_likes')
->whereRaw('employer_likes.employer_id = applicant_likes.liked_employer_id');
})
->get();
return view('applicant.employers.matched', compact('matches'));
}
}
Here's the Applicant model where below I extracted the logic into a usable Traits
App\Models\Applicant
class Applicant extends Authenticatable
{
use Notifiable, LikeableEmployer, MatchableEmployer;
//
public function getAvatarAttribute($value)
{
return asset($value ?: '/images/default-avatar.jpeg');
}
}
App\Trais\LikeableEmployer
trait LikeableEmployer
{
public function likeEmployer(Employer $employer)
{
return $this->likedEmployers()->save($employer);
}
public function unlikeEmployer(Employer $employer)
{
return $this->likedEmployers()->detach($employer);
}
public function toggleLikeEmployer(Employer $employer)
{
if ($this->likingEmployer($employer)) {
return $this->unlikeEmployer($employer);
}
return $this->likeEmployer($employer);
}
public function likingEmployer(Employer $employer)
{
return $this->likedEmployers()->where('liked_employer_id', $employer->id)->exists();
}
public function likedEmployers()
{
return $this->belongsToMany(Employer::class, 'applicant_likes', 'applicant_id', 'liked_employer_id');
}
}
finally, here's where the matched logic should be placed
namespace App\Traits;
use App\Traits\LikeableApplicant;
use App\Traits\LikeableEmployer;
trait MatchableEmployer
{
use LikeableApplicant, LikeableEmployer;
public function matchedEmployers()
{
//
}
}
You need to create a table where you will store the matches. Let's take the following example.
relationships table: id | from | to, It's a match if we have a pair. Example:
id | from | to
1 | 1 | 2
2 | 2 | 1
Now create Relationship Model
class Relationship extends Model
{
public static function getMatch($user_id)
{
return self::leftJoin('relationship reverse', 'relationship.to', '=', 'reverse.from')->where('relationship.from', 'reverse.to')->where('relationship.from', $user_id)->get();
}
}
Now you can simply call User::getMatch('any_user_id');
First of all, create the model for every table you used in this query, then add the following relationship.
In ApplicantLike Model
public function employer(){
return $this->belongsTo('App\Employer','liked_employer_id','id');
}
In Employer Model
public function likes(){
return $this->hasMany('App\EmployerLike','employer_id','id');
}
Final in your MatchedEmployersController
public function index()
{
$matches = ApplicantLike::with('employer','employer.likes')
->has('employer')
->has('employer.likes')
->get();
// dd($matches); // try with this first
return view('applicant.employers.matched', compact('matches'));
}
Try the above code, I converted your given code into ORM, but I think that you are implementing the wrong logic for what you need. If anything will not work fine just reply to me I will help you.
[SOLVED] I'm not a pro on Laravel. Just started with web development. I was asked to make changes on an existing project which I downloaded from c Panel. On the server, the project was working fine. But after downloading it I'm getting the following error and not quite sure what's going on.
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'xyz.testimonials' doesn't exist (SQL: select * from testimonials)
After downloading the project I can the following
php artisan cache:clear
composer update
php artisan migrate
php artisan db:seed
The following the TestimonialController.php file
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Testimonial;
class TestimonialController extends Controller
{
public function index()
{
$testimonials = Testimonial::all();
return view('dashboard.testimonials.index')->withTestimonials($testimonials);
}
public function create()
{
return view('dashboard.testimonials.create');
}
public function store(Request $request)
{
$request->validate(['testimonial_text'=>'required']);
$testimonial = Testimonial::create($request->all());
if($testimonial)
{
$this->success('Testimonial added successfully');
}
else
{
$this->error();
}
return redirect()->back();
}
public function edit(Testimonial $testimonial)
{
return view('dashboard.testimonials.edit')->withTestimonial($testimonial);
}
public function update(Testimonial $testimonial,Request $request)
{
if($testimonial->update($request->all()))
{
$this->success('Testimonial Updated Successfully');
}
else
{
$this->error();
}
return redirect()->route('dashboard.testimonials.index');
}
public function destroy(Testimonial $testimonial)
{
if($testimonial->delete())
{
$this->success('Testimonial Deleted Successfully');
}
else
{
$this->error();
}
return redirect()->back();
}
}
Testimonial.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Testimonial extends Model
{
public $guarded = [];
public function allTestimonials()
{
return self::all();
}
}
There is two way of table define in Laravel.
model class name (testimonial) = singular and table
name(testimonials) = plural , Kindly please check if testimonials
is available or not in your database. whenever you don't define
$table into model, it means Laravel automatic search for table.
you have to manually add $table into Model fileas below. whenever you are not
creating table name in plural form as following first rule.
protected $table = 'testimonial';
Make sure about testimonials table exists in your xyz DB. If you've created table with another name then you've to define it in the model.
Let say, You've taken a table name as testimonial. then in your model, the protected field will be,
class Testimonial extends Model
{
protected $table = 'testimonial';
}
I am using Laravel 5.7 and now I am trying setup a relationship between three tables named:
Tickets (PK - TicketID, FK - CampusID)
Campus (PK - CampusID, FK - TechID)
User (PK - TechID)
I don't think I set up my models correctly as I am showing a ticket where the CampusID doesn't belong to the TechID. I am looking for a best practice on setting up Eloquent to keep the data integrity in place so I can prevent any abnormalities. As mentioned above the foreign key for Tickets should reference the Campus primary key, and Campus foreign key should reference the User primary key.
Here are my Models:
Ticket
protected $table='tickets';
public function user() {
return $this->belongsTo(User::class);
}
Campus
protected $table='campus';
public function user() {
return $this->belongsTo(User::class);
}
User
public function campus()
{
return $this->hasMany(Campus::class, 'TechID');
}
public function ticket()
{
return $this->hasMany(Ticket::class, 'AssignedTo');
}
Here is my controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
use App\Campus;
use App\Ticket;
class PagesController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
// Dashboard Page
public function index()
{
$user = Auth::user();
$campuses = Campus::where('TechID',$user->id)->pluck('CampusName');
$tickets = Ticket::all()->where('AssignedTo', $user->id);
return view('home')->with(['user' => $user,'campuses'=>$campuses,'tickets'=>$tickets]);
}
// Queue Page
public function Queue() {
return view('Pages.Queue');
}
// Reports Page
public function Reports() {
return view('Pages.Reports');
}
// Search Page
public function Search() {
return view('Pages.Search');
}
}
I think my models are fine, but my controller is probably where I made some mistakes. I've tried reading questions on here already, watching videos, and reading the Laravel docs, but nothing has really clicked with me yet. I really appreciate any and all help. Ideally it should cascade changes. So if I have a situation where I want to change what location a tech belongs to I could just make the change in the Campus table probably in the TechID column.
I would use Eager Loading.
public function index()
{
$user = User::with([
'campuses' => function($query) {
$query->select(['id', 'CampusName']);
},
'tickets'
])->where('id', Auth::id())->first();
$campuses = $user->campuses->pluck('CampusName');
$tickets = Ticket::all()->where('AssignedTo', $user->id);
return view('home')->with([
'user' => $user,
'campuses'=>$user->campuses->pluck('CampusName'),
'tickets'=>$user->tickets]);
}
EDIT
You need to update your User model.
public function campuses()
{
return $this->hasMany(Campus::class, 'TechID');
}
public function tickets()
{
return $this->hasMany(Ticket::class, 'AssignedTo');
}
Problem: I have accessor in Size.php model which is called in relationship with Item.php Model, in API i need the accessor to work, but in other controllers i want to disable the accessor. I have removed unnecessary/unrelated code from all files.
What i want to do:
In ItemControllerAPI i need accessor to work, but i want to disable accessor in other controllers.
I have already seen:
I have already seen these links but didn't work for me.
1: https://laracasts.com/discuss/channels/eloquent/accessor-on-demand-but-not-on-every-results
2: Create dynamic Laravel accessor
3: https://laracasts.com/discuss/channels/general-discussion/eager-load-accessors
Size.php (Model)
class Size extends Model
{
protected $appends = ['addons'];
public function items()
{
return $this->belongsToMany('App\Item', 'items_sizes')->withPivot('price');//->withTimestamps();
}
public function getAddonsAttribute($value)
{
$addon = Addon::where('addons.category_id', $this->category_id)
->where('size_id', $this->id)
->get();
return $addon;
}
}
Item.php (Model)
class Item extends Model
{
public function options()
{
return $this->belongsToMany('App\Option', 'items_options')->withTimestamps();
}
public function sizes()
{
return $this->belongsToMany('App\Size', 'items_sizes')->withPivot('price');//->withTimestamps();
}
}
ItemControllerAPI.php (Controller)
class ItemControllerAPI extends BaseControllerAPI
{
public function show($id)
{
// If i call the Size model directly by using setAppends([]) its working fine,
// its removing the appended array from Size model
// $size = Size::all();
// $size->each->setAppends([]);
// return $size;
// If i use it with relationship it won't work.
// $itemSingleQuery = Item::with(['sizes' => function($query)
// {
// Doesn't work
// $query->setAppends([]);
// Doesn't work
// $query->each->setAppends([]);
// }])
// ->with('options')
// ->where('id', $id)
// ->get();
// query for getting data with relationships
$itemSingleQuery = Item::with('sizes')
->with('options')
->where('id', $id)
->get();
return $this->respondSuccess('content found', $itemSingleQuery);
}
}
I've found out how to do this:
After getting the entire collection we need to call setAppends() in each model, which contains appends, to add or remove them before serialization to array or JSON.
$itemSingleQuery = Item::with('sizes')->get();
$itemSingleQuery->each(function ($item) {
$item->sizes->each->setAppends(['addons']);
});
I would suggest that you set $appends when you need it:
$itemSingleQuery->pluck('sizes')->collapse()->each->setAppends(['addons']);
I am working on an exam/quiz app and it creates tests/quizzes for users and now I must create a set of spreadsheets that contain data such as the present students in a given exam, grades charts and so on.
Bu so far all I managed to create is a sheet with ALL the users using `->fromModel' but if I use any relation and or constrain I get an empty sheet.
I have this models:
<?php
namespace EMMA5;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class Exam extends Model
{
//
protected $dates = ['created_at', 'updated_at', 'applicated_at'];
protected $fillable = [
'applicated_at',
'duration',
'board_id',
'passing_grade',
'annotation'
];
public function board()
{
return $this->belongsTo('EMMA5\Board');
}
public function users()
{
return $this->belongsToMany('EMMA5\User')->withPivot('active', 'started_at', 'ended_at', 'seat', 'location_id');
}
...
User model (abbreviated)
class User extends Authenticatable
{
...
//Relations
public function answers()
{
return $this->hasMany(Answer::class);
}
public function exams()
{
return $this->belongsToMany('EMMA5\Exam')->withPivot('active', 'started_at', 'ended_at', 'location_id');
}
...
And I am trying to create a sheet with the users for a given exam:
(This is from my ExamController.php)
/**
* Returns a spreadsheet with only the students that were present
*
* #return PHPOffice
*/
public function gradesSpreadshet(Exam $exam)
{
$grade = new Grade;
$gradedStudents = $grade->allStudents($exam)->toArray();
//dd(\EMMA5\Exam::find(195)->with('users')->get());
//dd($exam->answers->answer);
$data = $exam->users;
return Excel::create("FinalGrades", function ($excel) use($data) {
//Create sheet to be able to return something to keep on testing
//Another sheet
$excel->sheet('Primera hoja', function ($sheet) use($data) {
$sheet->fromArray($data);
});
})->export('xlsx');
}
And I get an empty sheet.
I already tried with ->fromArray() and ->fromModel() .
Will appreciate any input.
Some time passed and nobody answered but I found a solution.
I do not know if it will be helpful for someone else.
The way I got the results couldn't be read by Excel Laravel. So I created a helper function with a callback.
public static function collectionToArray(Array $collect = null)
{
return array_map(function ($array) use($collect)
{
foreach ($array as $key => $value) {
$resultArray[$key] = $value;
}
return $resultArray;
}, $collect);
}
This returns a simplified version of the Collection that can be easily read by Excel Laravel.