I`m trying to create a form-select field displaying all of the schools with a specified type. The laravel functionality of the code works. As I had this on one page and it all worked fine. But I have been asked to move them on to two separate pages. And my question is how do I get my $type variable from my storeType function into my school Selection function properly? See Code :
public function schoolSelection(School $school,$type)
{
$schools=$school->where('type','=',$type)->get();
return view('auth.schoolSelection',compact('schools'));
}
public function storeType(Request $request, School $school)
{
$data=$request->all();
$type=$data['schoolType'];
return redirect()->route('schoolSelection',compact('type'));
}
Routes :
Route::get('schoolSelection/type',[RegisteredUserController::class,'schoolType'])->name('schoolType');
Route::get('schoolSelection/school',[RegisteredUserController::class,'schoolSelection'])->name('schoolSelection');
Route::post('schoolSelection/type',[RegisteredUserController::class,'storeType'])->name('type.store');
Route::post('schoolSelection/school',[RegisteredUserController::class,'schoolSelection'])->name('schoolSelection.store');
if both the functions are in same controller than you can make type as global variable .
class TestController extends Controller
{
private $type;
public function storeType(Request $request, School $school)
{
$data=$request->all();
$this->type=$data['schoolType'];
return redirect()->route('schoolSelection',compact('type'));
}
public function schoolSelection(School $school)
{
$type = $this->$type;
$schools=$school->where('type','=',$type)->get();
return view('auth.schoolSelection',compact('schools'));
}
}
Related
I am trying to create Main site navigation, Sidebar Navigation and Footer navigation in Fat Free environment. I am just starting to work with frameworks especially with MVC type.
My problem, since my navigation will be almost on every page of the website, I was thinking about creating separate controller and model to handle all this staff, but not sure how it would work without making routing?
Also, I am not sure how to handle join in the model, I could not find any information about this online at all.
Here is my current Category Controller
class Categories extends DB\SQL\Mapper
{
public function __construct(DB\SQL $db)
{
parent::__construct($db, 'categories');
}
public function all()
{
$this->load();
return $this->query;
}
public function getByID($id)
{
$this->load(array('id=?', $id));
return $this->query;
}
public function getBySlug($category_slug)
{
$this->load(array('category_slug=?', $category_slug));
return $this->query;
}
public function add()
{
$this->copyfrom('POST');
$this->save();
}
public function edit($id)
{
$this->load(array('id=?', $id));
$this->copyfrom('POST');
$this->update();
}
public function delete($id)
{
$this->load(array('id=?', $id));
$this->erase();
}
}
any ideas or pointers will help me to go a long way.
Thanks in advance
I don't know if understood what your issue is, but if you want to make the categories available for all methods in a Controller, you could use the beforeRoute() method:
class TestController extends MainController {
// runs before routing
// if another controller extends TestController and also has a
// beforeRoute, this will be overriden
function beforeRoute() {
// Load Categories
$categories = new Categories($this->db);
// Assiging ->all() to variable makes the method return an array of all results
$categoriesArray = $categories->all();
// Set an array in the hive for template use
$this->f3->set('categories', $categoriesArray );
// Clear the instance
$categories->reset();
}
function renderPage() {
// the 'categories' hive variable is available because beforeRoute has been run
// Set the page title from the dictionary file
$this->f3->set('pageTitle', $this->f3->get('DICT_'.'page_whatever') );
// Render the View
$this->f3->set('view','page.whatever.htm');
$template=\Template::instance();
echo $template->render('layout.sidebar.htm');
}
// End of Controller
}
And of course, in the template:
<repeat group="#categories" value="#category">
<li>
{{ #category.label }}
</li>
</repeat>
ps: You might be using $f3 instead of $this->f3 (and the same for $db)
In my application i have 4 models that relate to each other.
Forms->categories->fields->triggers
What I am trying to do is get the Triggers that refer to the current Form.
Upon researching i found nested eager loading, which would require my code to look like this
Form::with('categories.fields.triggers')->get();
Looking through the response of this i can clearly see the relations all the way down to my desired triggers.
Now the part I'm struggling with is only getting the triggers, without looping through each model.
The code i know works:
$form = Form::findOrFail($id);
$categories = $form->categories;
foreach ($categories as $category) {
$fields = $category->fields;
foreach ($fields as $field) {
$triggers[] = $field->triggers;
}
}
I know this works, but can it be simplified? Is it possible to write:
$form = Form::with('categories.fields.triggers')->get()
$triggers = $form->categories->fields->triggers;
To get the triggers related? Doing this as of right now results in:
Undefined property: Illuminate\Database\Eloquent\Collection::$categories
Since it is trying to run the $form->categories on a collection.
How would i go about doing this? Do i need to use the HasManyThrough relation on my models?
My models
class Form extends Model
{
public function categories()
{
return $this->hasMany('App\Category');
}
}
class Category extends Model
{
public function form()
{
return $this->belongsTo('App\Form');
}
public function fields()
{
return $this->hasMany('App\Field');
}
}
class Field extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
public function triggers()
{
return $this->belongsToMany('App\Trigger');
}
}
class Trigger extends Model
{
public function fields()
{
return $this->belongsToMany('App\Field');
}
}
The triggers run through a pivot table, but should be reachable with the same method?
I created a HasManyThrough relationship with unlimited levels and support for BelongsToMany:
Repository on GitHub
After the installation, you can use it like this:
class Form extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function triggers() {
return $this->hasManyDeep(Trigger::class, [Category::class, Field::class, 'field_trigger']);
}
}
Form::with('triggers')->get();
Form::findOrFail($id)->triggers;
So I have Model, View and Controller, my code works but i have no one to educate me if I do work with it properly.
I won't copy paste the whole code, so therefor I've drawed how it works:
THE PICTURE: MVC
The part of code:
class Site {
protected $config;
function __construct() {
$this->config = include("resources/config.php");
}
private function connect() { /*database connection*/ }
public function getData($var) {
/* connecting, $var = amout of rows, and storing the data in array() */
}
}
class SiteView {
private $data;
function __construct(Site $data) {
$this->model = $data;
}
public function output() {
if(!empty($this->model->data)) { /* displays the data */ }
}
public function render($template) {
return include("$template");
}
}
class SiteController {
public function __construct(Site $respond) {
$this->model = $respond;
}
public function condition() {
$view = new SiteView($this->model);
$view->render("header.php");
if(!isset($_GET['action'])) {
$view->render("body.php");
} else if($_GET['action'] === "report" AND isset($_GET['id'])) {
$view->render("report_body.php");
} else if ...
}
So the model and view is used in templates, and I'm not sure if it is a good thing or bad. Thanks for any kind of help or showing me the way.
The MVC or Model, View and Controller approach is Model is for data which used by user, Controller is the backend logic and View is the output in HTML or the User Interface (UI).
Normally every request come to the controller first. Controller is connected with the Model and View. Controller collect the data according to the request from Model and send the data to the View for show. View can not able to connect with model.
For more details see this link, Click Here
Looks simple (and maybe) but I need pass a received variable in a function to another function. Here's my code:
PD: I using Laravel Eloquent's Scopes
class myParentModel extends Model {
public function scopeMyScope($query, $VAR_I_WANT_TO_PASS=[]) {
return $query->with('model'])->whereHas('model', function($q, $VAR_I_WANT_TO_PASS=[]) {
$q->where('colum1',$VAR_I_WANT_TO_PASS[0])->where('colum2',$VAR_I_WANT_TO_PASS[1])->where('colum3',$VAR_I_WANT_TO_PASS[2]);
})->take(10);
}
}
and I want to do this:
$result = myParentModel::myScope([3,1,6])->get();
I resolve this using use:
class myParentModel extends Model {
public function scopeMyScope($query, $VAR_I_WANT_TO_PASS) {
return $query->with('model'])->whereHas('model', function($q) use ($VAR_I_WANT_TO_PASS) {
$q->where('colum1',$VAR_I_WANT_TO_PASS[0])->where('colum2',$VAR_I_WANT_TO_PASS[1])->where('colum3',$VAR_I_WANT_TO_PASS[2]);
})->take(10);
}
}
Is it possible to pass, somehow, a parameter to a relationship function?
I have currently the following:
public function achievements()
{
return $this->belongsToMany('Achievable', 'user_achievements')->withPivot('value', 'unlocked_at')->orderBy('pivot_unlocked_at', 'desc');
}
The problem is that, in some cases, it does not fetch the unlocked_at column and it returns an error.
I have tried to do something like:
public function achievements($orderBy = true)
{
$result = $this->belongsToMany (...)
if($orderBy) return $result->orderBy(...)
return $result;
}
And call it as:
$member->achievements(false)->(...)
But this does not work. Is there a way to pass parameters into that function or any way to check if the pivot_unlocked_at is being used?
Well what I've did was just adding new attribute to my model and then add the my condition to that attirbute,simply did this.
Class Foo extends Eloquent {
protected $strSlug;
public function Relations(){
return $this->belongsTo('Relation','relation_id')->whereSlug($this->strSlug);
}
}
Class FooController extends BaseController {
private $objFoo;
public function __construct(Foo $foo){
$this->objFoo = $foo
}
public function getPage($strSlug){
$this->objFoo->strSlug = $strSlug;
$arrData = Foo::with('Relations')->get();
//some other stuff,page render,etc....
}
}
You can simply create a scope and then when necessary add it to a builder instance.
Example:
User.php
public function achievements()
{
return $this->hasMany(Achievement::class);
}
Achievement.php
public function scopeOrdered(Builder $builder)
{
return $builder->orderBy(conditions);
}
then when using:
//returns unordered collection
$user->achievements()->get();
//returns ordered collection
$user->achievements()->ordered()->get();
You can read more about scopes at Eloquent documentation.
You can do more simple, and secure:
When you call the relation function with the parentesis Laravel will return just the query, you will need to add the get() or first() to retrieve the results
public function achievements($orderBy = true)
{
if($orderBy)
$this->belongsToMany(...)->orderBy(...)->get();
else
return $this->belongsToMany(...)->get();
}
And then you can call it like:
$member->achievements(false);
Works for the latest version of Laravel.
Had to solve this another was as on Laravel 5.3 none of the other solutions worked for me. Here goes:
Instantiate a model:
$foo = new Foo();
Set the new attribute
$foo->setAttribute('orderBy',true);
Then use the setModel method when querying the data
Foo::setModel($foo)->where(...)
This will all you to access the attribute from the relations method
public function achievements()
{
if($this->orderBy)
$this->belongsToMany(...)->orderBy(...)->get();
else
return $this->belongsToMany(...)->get();
}