How to create controller for data in laravel? - php

Here is the current code I have for the model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Courses extends Model
{
protected $table = 'courses';
foreach ($courses as $course) {
echo $course->course;
}
}
Is this coded correctly? The data is being fetched from the 'courses' table and 'courses' is the name of the column.
I am adding a new feature to my search directory. The profiles contain variables from the database so there is a lot of data being fetched from the same database table. There is one data, however, that is being put into a separate table because it can't fit in the same table as the other data. So I have to figure out a way to fetch that data from the other database table and put it into the profile code.
Here is the controller for the profile page (the snippet that controls the view):
//view school
public function viewschool ($url){
$url ='schools/' . $url;
if (count(School::where('url', '=', $url)->first()) <> 1 ) {
return redirect()->back();
}
$sch = School::where('url', '=', $url)->first();
$articles = posts::where('post_type','article')->where('school',$sch->name)->take(3)->get();
$news = posts::where('post_type','news')->where('school',$sch->name)->take(3)->get();
$others = posts::where('post_type','news')->take(3)->get();
return view('school-info')
->with(array('sch' => $sch,'school_articles' => $articles,'school_news' => $news,'others' => $others));
}
The new data are the school courses. the database table for courses contain columns for school ID (basically the courses are matched up to the ID of the school name they belong to in the schools table) as well as other data such as duration of course and tuition.
Am wondering how do I create the controller code for the school courses?

So first improve your understanding of the Model in Laravel. You just define the properties for your classes there. The foreach is totally out of place there.
An example Model should look like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Course extends Model
{
protected $table = 'courses';
protected $fillable = ['properties'];
}
So you would've start with a "fresh" and ready to use Model. Every Action with your Model you do inside your Controller. But DB Queries you do inside a Repository.
And now regarding your Question:
You can define relationships within Models via e.g.
protected $searchable =
[
'relations' => [
'schools' => [
'foreignKey' => 'school_id',
'foreignField' => 'courses'
]
]
]
Edit: forgot the method inside the model :D
public function schools(): BelongsTo
{
return $this->belongsTo(Schools::class);
}

Related

how to switch the database table in model based on condition in laravel

We have a table consignments which is having big data . so to keep our query quick we archive our old data to another table which is archive_consignments but in our consignment model I want that when I use eloquent like this
Consignment::find(1)
first it should try to get data from consignments table if it didn't found then it go to archive_consignments
is that possible to define this thing in eloquent model of Consignment
<?php
namespace App\Models\Admin;
use Illuminate\Database\Eloquent\Model;
use Nicolaslopezj\Searchable\SearchableTrait;
use Staudenmeir\EloquentHasManyDeep\HasRelationships;
use Laravel\Scout\Searchable;
class Consignment extends Model
{
// use SearchableTrait;
use Searchable;
use HasRelationships;
protected $table = 'consignments';
// following function to search by id(laravel scout)
public function getScoutKey()
{
return $this->id;
}
}
you could write using query builder
if(data not found in consignments )
{
$data = \DB::table('archive_consignments')->here your conditiion to find data
}
hope this will be useful.
What I would go with is to make ArchivedConsignment Model
Also I would make a function inside Repository that would be named something like queryConsignment and pass all my conditions as array for ex.
[ 'where' => ['column' => 'name', 'value' => 'someName'], 'whereIn' => ['column' => 'name', 'value' =>['bla','bla'] ]
Inside queryConsignment I would firstly call
$query = Consignment::newQuery()
after that I would apply all those conditions using a loop.
foreach($conditons as $method => $conditon){
$query->$method($condition['column'], $condition['value');
}
$data = $query->first();
At the end if there is no entry inside Consignment I would do the same with ArchivedConsignment

How to store and display one to many relationship in laravel api

I want to create API store function and display course and curriculum detail like this ERD, but I don't know how to make it
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Curriculum extends Model
{
/**
* Get the course that owns the comment.
*/
public function course()
{
return $this->belongsTo(Course::class,'course_id', 'id'));
}
}
Once the relationship has been defined, we can Store
use App\Models\Curriculum;
use App\Models\Course;
$course = Course::whereId($id)->first(); //it will give you a collection of Course model
Curriculum::create([
'name' => 'testing'
'course_id' => $course->id
]);
Once the relationship has been defined, we can retrieve a Curriculum's parent course by accessing the course "dynamic relationship property":
use App\Models\Curriculum;
$curriculum = Curriculum::find(1);
return $curriculum->course->title_course;

How do you define a 1-1 relationship bidirectionally with phalcon?

I have two tables, work_order and project. On the project records, there is a work_order_id field. There is no project_id on the work_order records. Do I need to add one?
Or is there a way to define these relationships using hasOne/belongsTo?
I've tried:
class WorkOrder extends \Phalcon\Mvc\Model {
public function initialize() {
$this->hasOne('id', Project::class, 'work_order_id');
}
}
class Project extends \Phalcon\Mvc\Model {
public function initialize() {
$this->hasOne('work_order_id', WorkOrder::class, 'id');
}
}
I can retrieve the WorkOrder from the project like so: $project->workOrder, but I cannot retrieve a Project from a WorkOrder using $workOrder->project. I want a bidirectional relationship.
How do I do this?
Try adding the alias parameter, since the implicit retrieval might try to use the class name and it wouldn't support namespaces in your models.
I found it quite bogus in phalcon 1/2/3 to work with hasOne. I've been using belongsTo since then until I re-wrote the pre-post-save part of the phalcon relationship manager for my personal needs. Keep in mind that belongsTo will be saved before the main model you are working with, other types of relationships will be created/updated after the main record is saved. I choose to use "belongsTo" or "hasOne" depending on the order that I want the records and their relationships to be saved.
class WorkOrder extends \Phalcon\Mvc\Model {
public function initialize() {
$this->belongsTo('project_id', Project::class, 'id', ['alias' => 'Project']);
}
}
class Project extends \Phalcon\Mvc\Model {
public function initialize() {
$this->hasOne('id', WorkOrder::class, 'project_id', ['alias' => 'WorkOrder']);
$this->hasMany('id', WorkOrder::class, 'project_id', ['alias' => 'WorkOrderList']);
}
}
Implicit retrieval should start with a ucfirst camelized string of your class name, or using a get.
$workOrder = WorkOrder::findFirst();
$project = $workOrder->Project;
$project = $workOrder->getProject(['deleted <> 1']);
$workOrderList = $project->WorkOrderList;
$workOrder = $project->WorkOrder;
$workOrder = $project->getWorkOrder(['deleted <> 1', 'order' => 'projectId desc']);

Laravel Eloquent one to many relationship not working

I'm obviously missing something. I thought I was comfortable around laravel relationships...
I've 2 tables, named ratings and ratingdetails. The models are named Rating & Ratingdetail:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Rating extends Model
{
public function ratingdetails()
{
return $this->hasMany('App\Ratingdetail');
}
public function campaigns()
{
return $this->hasMany('App\Campaign');
}
}
and
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
class Ratingdetail extends Model
{
use HasTranslations;
public $translatable = ['value'];
public function rating()
{
return $this->belongsTo('App\Rating');
}
}
When I try to access to my Rating model it works fine, but I can't access the relationships; the output is the following, despite there should be 4 Ratingdetails rows...:
{"id":1,"description":"fontawesome","created_at":null,"updated_at":null,"deleted_at":null}
Thank you all for your time !
$rating = Rating::find($request->rating_id);
return $rating->toJson();
In the above line of code, you're never accessing the ratingdetails relationship. They are not included by default, and need to be loaded before being available:
$rating = Rating::with(["ratingdetails"])->find($request->rating_id);
return $rating->toJson();
Including it via with() will "Eager load" the relationship and expose it to be accessed via
console.log(rating.ratingdetails);
// Will contain an array of 4 objects
Before converting to json, you'd be able to access $rating->ratingdetails, but once converted, you lose access unless you have previously loaded the relationship.
Actually I can't answer for this question without having the Models' $fillable attributes, or without DB Tables structures. But I think your tables have following columns:
"raitings" -> "id", "description", "created_at", "updated_at", "deleted_at"
"raitingdetails" -> "id", "raiting_id", "value", ...
In normal way, you need to create OneToMany relation for that 2 tables with foreign key. So in your "raitingdetails" migration you need to have something like this:
$table->unsignedBigInteger('raiting_id')->nullable();
$table->foreign('raiting_id')->references('id')->on('raitings')->onUpdate('cascade')->onDelete('cascade');
Your models are correct, but it not just cool now.. You can improve them by adding $fillable columns and FKs of relations (Note: if you're using traditional foreign key concept, like "partents.id"->"childs.partent_id", then you can leave this part too).
For getting all Rating details of 1 Rating, you can do this:
$rating = Rating::find($rating_id);
$rating_details_of_one = $rating->ratingdetails()->get()->toJson();
If you want to have Rating Details for all actions, you can add Accessor in your Rating model and attach that to $appends like this:
protected $appends = [ 'rating_details' ]; public function
public function getRatingDetailsAttribute() {
return $this->ratingdetails;
}
And in logic parts you can access like this:
$ratings = Rating::find($rating_id); // this will get with their "ratingdetails" relation
Or you can attach accessor on the fly without protected $appends and getRatingDetailsAttribute() function like this:
$rating = Rating::find($rating_id);
$rating_details_of_one = $rating->setAppends([ 'rating_details' ])->get()->toJSON();
If you want to have some Ratings with their details, you can use something like this:
$rating_details_of_many = Rating::where('description', 'fontawesome')->with('ratingdetails')->get()->toJson();

getting the value of an extra pivot table column laravel

I have a phone_models, phone_problems, and a phone_model_phone_problem pivot table. The pivot table has an extra column 'price'.
PhoneModel:
class PhoneModel extends \Eloquent
{
public function problems()
{
return $this->belongsToMany('RL\Phones\Entities\PhoneProblem')->withPivot('price');
}
}
PhoneProblem:
class PhoneProblem extends \Eloquent
{
public function models()
{
return $this->belongsToMany('PhoneModel')->withPivot('price');
}
}
What I'm trying to do is get the price of a specific phone with a specific problem.
This is how I have it now but I feel like Laravel has a built in Eloquent feature I can't find to do this in a much simpler way:
$model = $this->phoneService->getModelFromSlug($model_slug);
$problem = $this->phoneService->getProblemFromSlug($problem_slug);
all this does is select the specific model and problem from their slug.
then what I do is with those credentials I get the price like so:
$row = DB::table('phone_model_phone_problem')
->where('phone_model_id', '=', $model->id)
->where('phone_problem', '=', $problem->id)
->first();
so now I can get the price like so $row->price but I feel like there needs to be a much easier and more 'Laravel' way to do this.
When using Many to Many relationships with Eloquent, the resulting model automatically gets a pivot attribute assigned. Through that attribute you're able to access pivot table columns.
Although by default there are only the keys in the pivot object. To get your columns in there too, you need to specify them when defining the relationship:
return $this->belongsToMany('Role')->withPivot('foo', 'bar');
Official Docs
If you need more help the task of configuring the relationships with Eloquent, let me know.
Edit
To query the price do this
$model->problems()->where('phone_problem', $problem->id)->first()->pivot->price
To get data from pivot table:
$price = $model->problems()->findOrFail($problem->id, ['phone_problem'])->pivot->price;
Or if you have many records with different price:
$price = $model->problems()->where('phone_problem', $problem->id)->firstOrFail()->pivot->price;
In addition.
To update data in the pivot you can go NEW WAY:
$model->problems()->sync([$problemId => [ 'price' => $newPrice] ], false);
Where the 2nd param is set to false meaning that you don't detach all the other related models.
Or, go old way
$model->problems()->updateExistingPivot($problemId, ['price' => $newPrice]);
And remind you:
To delete:
$model->problems()->detach($problemId);
To create new:
$model->problems()->attach($problemId, ['price' => 22]);
It has been tested and proved working in Laravel 5.1 Read more.
Laravel 5.8~
If you want to make a custom pivot model, you can do this:
Account.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Account extends Model
{
public function users()
{
return $this->belongsToMany(User::class)
->using(AccountUserPivot::class)
->withPivot(
'status',
'status_updated_at',
'status_updated_by',
'role'
);
}
}
AccountUserPivot.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class AccountUserPivot extends Pivot
{
protected $appends = [
'status_updated_by_nice',
];
public function getStatusUpdatedByNiceAttribute()
{
$user = User::find($this->status_updated_by);
if (!$user) return 'n/a';
return $user->name;
}
}
In the above example, Account is your normal model, and you have $account->users which has the account_user join table with standard columns account_id and user_id.
If you make a custom pivot model, you can add attributes and mutators onto the relationship's columns. In the above example, once you make the AccountUserPivot model, you instruct your Account model to use it via ->using(AccountUserPivot::class).
Then you can access everything shown in the other answers here, but you can also access the example attribute via $account->user[0]->pivot->status_updated_by_nice (assuming that status_updated_by is a foreign key to an ID in the users table).
For more docs, see https://laravel.com/docs/5.8/eloquent-relationships (and I recommend press CTRL+F and search for "pivot")

Categories