I am trying to pre-populate some fields in a form and I'm new to relationships.
My controller:
public function index($supplierId) {
$Supplier = new Supplier;
$supplierData = Supplier::find($supplierId);
$supplierData->countryId = ($supplierData->countryId == 0 ? 258 : $supplierData->countryId);
$supplierData->writtenLanguageId = ($supplierData->writtenLanguageId == 0 ? 1 : $supplierData->writtenLanguageId);
$supplierData->paymentTermsId = ($supplierData->paymentTermsId == 0 ? 5 : $supplierData->paymentTermsId);
$countries = Countries::lists('country', 'id');
$languages = Languages::lists('language', 'id');
$paymentTerms = PaymentTerms::lists('term', 'id');
$leadTimes = Leadtimes::lists('leadtime', 'id');
return View::make('supplier.supplier', array(
'supplierData' => $supplierData,
'countries' => $countries,
'languages' => $languages,
'paymentsTerms' => $paymentTerms,
'leadtimes' => $leadTimes
));
}
My model:
class Supplier extends Eloquent {
protected $table = 'suppliers';
public function email() {
return $this->hasOne('SupplierEmail', 'supplierId');
}
public function creditLimits() {
return $this->hasOne('SupplierCreditLimits', 'supplierId');
}
public function website() {
return $this->hasOne('SupplierWebsite', 'supplierId');
}
}
The problem:
<div class='col-xs-12 col-md-6'>{{Form::text('website', $supplierData->website->website, array('class' => 'form-control input-sm'))}}</div>
When there is no row (there is no record), I get:
Trying to get property of non-object (View: C:\wamp\vhosts\view\laravel\app\views\supplier\supplier.blade.php)
How do I get this to work properly?
In your view, use isset to check the value first:
<div class='col-xs-12 col-md-6'>
{{Form::text('website',
isset($supplierData->website->website) ? $supplierData->website->website : '',
array('class' => 'form-control input-sm'))
}}
</div>
Or, better yet, handle this logic in your controller and pass the result to the view:
$supplierData->URL = isset($supplierData->website->website) ? $supplierData->website->website : '';
Related
In the first time I want to save data to database from table this error appear.
ErrorException
Undefined variable: value
so I have to manually input the data from tinker or mysql
My Controller
public function store(Request $request)
{
$validateData = $request->validate([
'name_device_type' => 'required|max:255',
'signature' => 'Nullable'
]);
$id = DeviceType::getidDeviceTypes();
foreach ($id as $value); // Error happend in this line.
$lastdevicetypeId = $value->id;
$newdevicetypeId = $lastdevicetypeId + 1;
$GetnewdevicetypeId = sprintf('DT%04d', $newdevicetypeId);
$devicetypes = new DeviceType();
$devicetypes->idDeviceType = $GetnewdevicetypeId;
$devicetypes->name_device_type = $request->input('name_device_type');
$devicetypes->signature = $request->input('signature');
$devicetypes->save();
return redirect('/devicetypes')->with('success', 'New Device Type is added');
}
My Migration table
public function up()
{
Schema::create('device_types', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('idDeviceType');
$table->string('name_device_type');
$table->mediumText('signature');
$table->timestamps();
});
}
My create.blade.php
{!! Form::open(['action' => 'DeviceTypesController#store', 'method' => 'POST']) !!}
<div class="form-group">
{!! Form::label('name_device_type', 'Type Device'); !!}
{!! Form::text('name_device_type', '', ['class' => 'form-control', 'placeholder' => 'Type Device']); !!}
</div>
<div class="form-group">
{!! Form::label('signature', 'Signature (Optional)'); !!}
{!! Form::textarea('signature', '', ['id' => 'classic-ckeditor5', 'class' => 'form-control', 'placeholder' => 'Signature']); !!}
</div>
{{ Form::button('<i class="far fa-save"></i> Submit', ['type' => 'submit', 'class' => 'btn btn-info'] ) }}
{!! Form::close() !!}
the Model
class DeviceType extends Model
{
// Table Name
protected $table = 'device_types';
// Primary Key
protected $primaryKey = 'idDeviceTypes';
// Timestamps
public $timestamps = true;
public $incrementing = false;
public static function getidDeviceType(){
return $getidDeviceType = DB::table('device_types')->orderBy('id','desc')->take(1)->get();
}
}
But if the table has data this error disappear, also this error will appear again if I remove every data and made the table empty.
You have a Semicolon right after the foreach loop definition: foreach ($id as $value);
and you are using the $value in the next line $lastdevicetypeId = $value->id; which is outside the scope of your loop.
You should remove the ; following the the foreach loop and change it to : and add a endforeach; where you want to end the loop.
Example:
foreach ($id as $value):
$lastdevicetypeId = $value->id;
$newdevicetypeId = $lastdevicetypeId + 1;
$GetnewdevicetypeId = sprintf('DT%04d', $newdevicetypeId);
$devicetypes = new DeviceType();
$devicetypes->idDeviceType = $GetnewdevicetypeId;
$devicetypes->name_device_type = $request->input('name_device_type');
$devicetypes->signature = $request->input('signature');
$devicetypes->save();
endforeach;
Or you can write this code as:
foreach ($id as $value){
$lastdevicetypeId = $value->id;
$newdevicetypeId = $lastdevicetypeId + 1;
$GetnewdevicetypeId = sprintf('DT%04d', $newdevicetypeId);
$devicetypes = new DeviceType();
$devicetypes->idDeviceType = $GetnewdevicetypeId;
$devicetypes->name_device_type = $request->input('name_device_type');
$devicetypes->signature = $request->input('signature');
$devicetypes->save();
}
You could grab the max 'id' of the table and add 1 to it without having to grab a whole record:
...
// validation
$newdevicetypeId = DeviceType::max('id') + 1;
$GetnewdevicetypeId = sprintf('DT%04d', $newdevicetypeId);
// new DeviceType
...
There is the option of having a model event that can set this particular field after the record has been created so it has its own id to use.
I have multiple forms where I need to pass through the id. In the example bellow I have 2 controllers one is for Courses and one is for the Exams. I'm trying to create a course and then pass through the course id to the exam form.
Here is what I've tried but the value is not passing through.
Course Controller:
public function store(StoreCoursesRequest $request)
{
if (! Gate::allows('course_create')) {
return abort(401);
}
$request = $this->saveFiles($request);
$course = Course::create($request->all()
// $status = array('assigned' => 'assigned', 'canceled'=>'canceled');
+ ['position' => Course::where('curriculum_id', $request->curriculum_id)->max('position') + 1]);
$trainers = \Auth::user()->isAdmin() ? array_filter((array)$request->input('trainers')) : [\Auth::user()->id];
$course->trainers()->sync($trainers);
$course->roles()->sync(array_filter((array)$request->input('roles')));
$course->assigned_user()->sync(array_filter((array)$request->input('assigned_user')));
$curriculum = Curriculum::get(array('id' => 'id'));
$exam = Exam::get(array('id' => 'id'));
foreach ($request->input('course_materials_id', []) as $index => $id) {
$model = config('medialibrary.media_model');
$file = $model::find($id);
$file->model_id = $course->id;
$file->save();
}
session('id', 'id');
return redirect()->route('admin.exams.create');
}
Here is the exams controller
public function create()
{
if (! Gate::allows('exam_create')) {
return abort(401);
}
$exam_assigneds = \App\Exam::get()->pluck('title', 'id')->prepend(trans('global.app_please_select'), '');
$questions = \App\ExamQuestion::get()->pluck('question', 'id');
$in_classes = \App\InClassCourse::get()->pluck('title', 'id')->prepend(trans('global.app_please_select'), '');
$reoccurance_type = \App\ReoccuranceType::get()->pluck('type', 'id')->prepend(trans('global.app_please_select'), '');
$courses = session('id');
return view('admin.exams.create', compact('courses', 'exam_assigneds', 'questions', 'in_classes', 'reoccurance_type'));
}
Here is the view
<div class="row">
<div class="col-xs-12 form-group">
{!! Form::label('course_id', trans('global.exam.fields.course').'', ['class' => 'control-label']) !!}
{!! Form::text('id', $courses, old('id'), ['class' => 'form-control', 'placeholder' => '']) !!}
<p class="help-block"></p>
#if($errors->has('course_id'))
<p class="help-block">
{{ $errors->first('course_id') }}
</p>
#endif
</div>
</div>
All I'm getting is just text value of id. It doesn't pull the actual id.
In Course Controller modify
session('id', 'id');
to
session('id', $course->id);
I have a company table and an attributes table with all sorts of value in it.
One company hasMany attributes and an attribute belongsTo a company.
Now I have a value inside the attributes table with a 'account_nr_start' (for example, when a new user is added to a company its account_id starts counting up from 1000).
Controller:
public function __construct(Company $company, User $user)
{
if(Auth::user()->usertype_id == 7)
{
$this->company = $company;
}
else
{
$this->company_id = Auth::user()->company_id;
$this->company = $company->Where(function($query)
{
$query->where('id', '=', $this->company_id )
->orWhere('parent_id','=', $this->company_id);
}) ;
}
$this->user = $user;
$this->middleware('auth');
}
public function edit(Company $company, CompaniesController $companies)
{
$companies = $companies->getCompaniesName(Auth::user()->company_id);
$attributes = $company->attributes('company')
->where('attribute', '=', 'account_nr_start')
->get();
foreach ($attributes as $k => $v) {
$nr_start[] = $v->value;
}
return view('company.edit', ['company' => $company, 'id' => 'edit', 'companies' => $companies, 'nr_start' => $nr_start]);
}
public function update(UpdateCompanyRequest $request, $company, Attribute $attributes)
{
$company->fill($request->input())->save();
$attributes->fill($request->only('company_id', 'attribute_nr', 'value'))->save();
return redirect('company');
}
HTML/Blade:
<div class="form-group {{ $errors->has('_nr_') ? 'has-error' : '' }}">
{!! HTML::decode (Form::label('account_nr_start', trans('common.account_nr_start').'<span class="asterisk"> *</span>', ['class' => 'form-label col-sm-3 control-label text-capitalize'])) !!}
<div class="col-sm-6">
{!! Form::text('value', $nr_start[0], ["class"=>"form-control text-uppercase"]) !!}
{!! $errors->first('account_nr_start', '<span class="help-block">:message</span>') !!}
</div>
</div>
When I update a company now, it will upload like the last input here: :
So it makes a new rule, while it needs to edit the current attribute rule instead of making a new rule with an empty company_id/attribute.
If I understand what you are trying to do, I think this will fix your problem. The issue you have is the Attribute model is a new instance of the model rather than retrieving the model you need.
before running fill() from the attributes method try this
$new_attribute = $attributes->where('company_id', '=', $company->id)->where('attribute', '=', 'account_nr_start')->first();
Then run the fill()
$new_attribute->fill($request->only('company_id', 'attribute_nr', 'value'))->save();
Newbie to PHP/Laravel here so please be patient.
I have a webpage that is searching based on 3 criteria for dogs , breed, sex and radius.
here is the relevant code:
search page
<div class="col-md-12 zero-pad-left zero-pad-right">
{{ Form::open(array('action' => array('DogsController#index'), 'class'=>'form width88', 'role'=>'search', 'method' => 'GET')) }}
<div id="prefetch">
{{ Form::text('search-breed', null, array('class' => 'typeahead form-group form-control', 'placeholder' => 'Search by breed here...')) }}
{{ Form::text('sex', null, array('class' => 'form-group form-control', 'placeholder' => 'Search by sex here...')) }}
{{ Form::text('miles', null, array('class' => 'form-group form-control', 'placeholder' => 'Search by distance here...')) }}
</div>
{{ Form::submit('Search', array('class' => 'btn btn-default search-bar-btn')) }}
{{ Form::close() }}
ControllerPage
class DogsController extends \BaseController {
public function __construct()
{
// call base controller constructor
parent::__construct();
// run auth filter before all methods on this controller except index and show
$this->beforeFilter('auth', array('except' => array('show')));
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
if (Input::has('search')) {
$queryString = Input::get('search');
$dogs = Dog::where('name', 'LIKE', "%$queryString%")->orderBy('name')->paginate(5);
}
elseif (Input::has('search-breed'))
{
$dogs = Dog::whereHas('breed', function($q)
{
$queryString = Input::get('search-breed');
$q->where('name', 'LIKE', "%$queryString%");
})->orderBy('name')->paginate(5);
} //end elseif
else {
$dogs = Dog::orderBy('name')->paginate(5);
} //end else
return View::make('dogs.index')->with(array('dogs' => $dogs));
} //end function index()
when i enter a search for poodle, male, within 20 miles, the url shows as follows:
http://ruff-love.dev/dogs?search-breed=poodle&sex=M&miles=20
The search currently works ok when searching for just breed.
I cant seem to figure out the syntax to add the SEX and RADIUS criteria also.
it should allow for those criteria to be null and still perform the query.
any advice would be greatly apprecaited
You can use query scopes http://laravel.com/docs/eloquent#query-scopes to make it verbose and easier in your controller (or wherever you will be doing it in future) then chain them according to your needs:
// Dog model
public function scopeSearchBreed($query, $breed)
{
$query->whereHas('breed', function ($q) use ($breed) {
$q->where('name', 'like', "%{$breed}%");
});
}
public function scopeWithinRadius($query, $radius)
{
$query->where(...); // do math here
}
Then all you need is this:
public function index()
{
$q = Dog::query();
if (Input::has('search'))
{
// simple where here or another scope, whatever you like
$q->where('name','like',Input::get('search'));
}
if (Input::has('search-breed'))
{
$q->searchBreed(Input::get('search-breed'));
}
if (Input::has('sex'))
{
$q->where('sex', Input::get('sex'));
}
if (Input::has('radius'))
{
$q->withinRadius(Input::get('radius'));
}
$dogs = $q->orderBy(..)->paginate(5);
// ...
Here's one possible solution, I think there are probably others. Create an empty query builder with the query() function and add the non-null clauses to it, then call the paginate() function at the end.
$builder = Dogs::query();
if (Input::has('search')) {
$queryString = Input::get('search');
$builder->where('name', 'LIKE', "%$queryString%");
}
// ... more clauses from the querystring
$dogs = $builder->orderBy('name')->paginate(5);
$builder = Dogs::query();
$term = Request::all();
if(!empty($term['breed'])){
$builder->where('breed','=',$term['breed']);
}
if(!empty($term['sex'])){
$builder->where('sex','=',$term['sex']);
}
if(!empty($term['radius'])){
$builder->where('radius','=',$term['radius']);
}
$result = $builder->orderBy('id')->get();
$area = Area::query();
if (Input::has('search')) {
$queryString = Input::get('search');
$area->where('name', 'LIKE', "%" . $queryString . "%");
}
$result = $area->orderBy('name')->paginate(5);
I need next & previous id record in database on Yii framework to make navigation buttons next and back ?
I added following functions in my model in Yii2:
public function getNext() {
$next = $this->find()->where(['>', 'id', $this->id])->one();
return $next;
}
public function getPrev() {
$prev = $this->find()->where(['<', 'id', $this->id])->orderBy('id desc')->one();
return $prev;
}
I made a function to get those ids your looking for. I suggest you to declare it in the model:
public static function getNextOrPrevId($currentId, $nextOrPrev)
{
$records=NULL;
if($nextOrPrev == "prev")
$order="id DESC";
if($nextOrPrev == "next")
$order="id ASC";
$records=YourModel::model()->findAll(
array('select'=>'id', 'order'=>$order)
);
foreach($records as $i=>$r)
if($r->id == $currentId)
return isset($records[$i+1]->id) ? $records[$i+1]->id : NULL;
return NULL;
}
So to use it all you have to do do is this:
YourModel::getNextOrPrevId($id /*(current id)*/, "prev" /*(or "next")*/);
It will return the corresponding id of the next or previous record.
I didn't test it, so give it a try and if something goes wrong please let me know.
Make a private var that is used to pass info to other functions.
In Model:
class Model1 .....
{
...
private _prevId = null;
private _nextId = null;
...
public function afterFind() //this function will be called after your every find call
{
//find/calculate/set $this->_prevId;
//find/calculate/set $this->_nextId;
}
public function getPrevId() {
return $this->prevId;
}
public function getNextId() {
return $this->nextId;
}
}
Check the code generated in the ViewDetal link and modify for the Prev/Net links in the _view file using
$model(or $data)->prevId/nextId
in the array('id'=>#) section.
Taking the original answer and adapting it for Yii2 with a little clean up:
/**
* [nextOrPrev description]
* #source http://stackoverflow.com/questions/8872101/get-next-previous-id-record-in-database-on-yii
* #param integer $currentId [description]
* #param string $nextOrPrev [description]
* #return integer [description]
*/
public static function nextOrPrev($currentId, $nextOrPrev = 'next')
{
$order = ($nextOrPrev == 'next') ? 'id ASC' : 'id DESC';
$records = \namespace\path\Model::find()->orderBy($order)->all();
foreach ($records as $i => $r) {
if ($r->id == $currentId) {
return ($records[$i+1]->id ? $records[$i+1]->id : NULL);
}
}
return false;
}
My implementation is based on SearchModel.
Controller:
public function actionView($id)
{
// ... some code before
// Get prev and next orders
// Setup search model
$searchModel = new OrderSearch();
$orderSearch = \yii\helpers\Json::decode(Yii::$app->getRequest()->getCookies()->getValue('s-' . Yii::$app->user->identity->id));
$params = [];
if (!empty($orderSearch)){
$params['OrderSearch'] = $orderSearch;
}
$dataProvider = $searchModel->search($params);
$sort = $dataProvider->getSort();
$sort->defaultOrder = ['created' => SORT_DESC];
$dataProvider->setSort($sort);
// Get page number by searching current ID key in models
$pageNum = array_search($id, array_column($dataProvider->getModels(), 'id'));
$count = $dataProvider->getCount();
$dataProvider->pagination->pageSize = 1;
$orderPrev = $orderNext = null;
if ($pageNum > 0) {
$dataProvider->pagination->setPage($pageNum - 1);
$dataProvider->refresh();
$orderPrev = $dataProvider->getModels()[0];
}
if ($pageNum < $count) {
$dataProvider->pagination->setPage($pageNum + 1);
$dataProvider->refresh();
$orderNext = $dataProvider->getModels()[0];
}
// ... some code after
}
OrderSearch:
public function search($params)
{
// Set cookie with search params
Yii::$app->response->cookies->add(new \yii\web\Cookie([
'name' => 's-' . Yii::$app->user->identity->id,
'value' => \yii\helpers\Json::encode($params['OrderSearch']),
'expire' => 2147483647,
]));
// ... search model code here ...
}
PS: be sure if you can use array_column for array of objects.
This works good in PHP 7+ but in lower versions you got to extract id by yourself. Maybe it's good idea to use array_walk or array_filter in PHP 5.4+
Full implemenentation with performance improvement by using DB engine/optimization (when id acts as primary key):
Model:
public static function getNextPrevId($currentId)
{
$queryprev = new Query();
$queryprev->select('max(id)')->from(self::tableName())->where('id<:id',['id'=>$currentId]);
$querynext = new Query();
$querynext->select('min(id)')->from(self::tableName())->where('id>:id',['id'=>$currentId]);
return [ $queryprev->scalar(), $querynext->scalar()];
}
Controller:
public function actionView($id) {
return $this->render('view', [
'model' => $this->findModel($id),
'nextprev' => YourModel::getNextPrevId($id),
]);
}
View:
<?= !is_null($nextprev[0]) ? Html::a('⇦', ['view', 'id' => $nextprev[0]], ['class' => 'btn btn-primary']) : '' ?>
<?= !is_null($nextprev[1]) ? Html::a('⇨', ['view', 'id' => $nextprev[1]], ['class' => 'btn btn-primary']) : '' ?>
The previous solutions are problematic when you get the the first or last record and they are making multiple calls to the database. Here is my working solution which operates on one query, handles end-of-table and disables the buttons at end-of-table:
Within the model:
public static function NextOrPrev($currentId)
{
$records = <Table>::find()->orderBy('id DESC')->all();
foreach ($records as $i => $record) {
if ($record->id == $currentId) {
$next = isset($records[$i - 1]->id)?$records[$i - 1]->id:null;
$prev = isset($records[$i + 1]->id)?$records[$i + 1]->id:null;
break;
}
}
return ['next'=>$next, 'prev'=>$prev];
}
Within the controller:
public function actionView($id)
{
$index = <modelName>::nextOrPrev($id);
$nextID = $index['next'];
$disableNext = ($nextID===null)?'disabled':null;
$prevID = $index['prev'];
$disablePrev = ($prevID===null)?'disabled':null;
// usual detail-view model
$model = $this->findModel($id);
return $this->render('view', [
'model' => $model,
'nextID'=>$nextID,
'prevID'=>$prevID,
'disableNext'=>$disableNext,
'disablePrev'=>$disablePrev,
]);
}
Within the view:
<?= Html::a('Next', ['view', 'id' => $nextID], ['class' => 'btn btn-primary r-align btn-sm '.$disableNext]) ?>
<?= Html::a('Prev', ['view', 'id' => $prevID], ['class' => 'btn btn-primary r-align btn-sm '.$disablePrev]) ?>