I am trying to set up a relationship with a project I am working on. The error I get is:
BadMethodCallException in Macroable.php line 81:
Method Organization does not exist.
Here is my store method.
public function store(Request $request)
{
$calendar_event = new CalendarEvent();
$calendar_event->title = $request->input("title");
$calendar_event->start = $request->input("start");
$calendar_event->end = $request->input("end");
$calendar_event->is_all_day = $request->input("is_all_day");
$calendar_event->background_color = $request->input("background_color");
$request->Organization()->calendar()->save($calendar_event);
return redirect()->route('calendar_events.index')->with('message', 'Item created successfully.');
}
My relationship in my CalendarEvent model is set up like this
public function Organization()
{
return $this->belongsTo('App\Organization');
}
The relationship in my Organization model is set up like this
public function calendar()
{
return $this->hasMany('App\CalendarEvent');
}
Thank you for your help.
Did you setup a route model binding? And even with that setup, i don't think you can access the model just from the request, you need to setup a proper parameter for the model you want injected.
public function store(Request $request, YourModel $model) {
}
Or the problem is that you are trying to save on $request, when you need to do that on $calendar_event, like this:
$calendar_event->Organization()->calendar()->save($calendar_event);
Related
After setting up a controller and a view to show a specific entry from my database, I wanted to use laravels function of Route Model Binding to fetch the data fromn the database and pass it to the view. However I am getting following error:
Symfony\Component\Debug\Exception\FatalThrowableError thrown with
message "Argument 2 passed to
Symfony\Component\HttpFoundation\RedirectResponse::__construct() must
be of the type integer, array given, called in
C:\xampp\htdocs\laravel\Cyberchess\vendor\laravel\framework\src\Illuminate\Routing\Redirector.php
on line 203"
I've tried to add this line to TrustProxy:
protected $headers = Request::HEADER_X_FORWARDED_ALL;
as the internet recommended, but when I opened the file, I realised it was already in the code.
My create/store works properly, which is why I assume it has something to do with Route Model Binding. I'm currently using a getRouteKeyName() to change the Key to 'AccID' so it should work.
//my controller
public function show(account $account){
//$account = account::where(['AccID' => $account])->get();
//dd($account);
return redirect('user.show', compact('account'));
}
//my model
class account extends Model
{
public function getRouteKeyName() {
return 'AccID';
}
public $timestamps = false;
}
//my view
<h1 class="title">Your Profile</h1>
<p>{{ $account->Nick }}</p>
I expected it to work just fine(duh), but got said error. When I dd(); the data, it has the information I want inside #attributes and in #original.
If if comment the dd() and let the return do it's work, I get the error.
The redirect() helper function is used to send a redirect 301 response from the server, what you want instead is to return a view like so
public function show(account $account)
{
$account = account::where(['AccID' => $account])->get();
return view('user.show', compact('account'));
}
I would like to create a question which has many surveys. In the questions Model:
public function surveys()
{
return $this->belongsToMany(Survey::class, 'survey__surveyquestions');
}
And in the controller when saving a new question:
private $questions;
public function __construct(QuestionsRepository $questions)
{
parent::__construct();
$this->questions = $questions;
}
public function store(Request $request)
{
$this->questions->create($request->all());
$this->questions->surveys()->attach($request->surveys);
return redirect()->route('admin.survey.questions.index')
->withSuccess(trans('core::core.messages.resource created', ['name' => trans('survey::questions.title.questions')]));
}
But I get the following error when it gets to the attach line:
(1/1) FatalErrorException Call to undefined method
Modules\Survey\Repositories\Eloquent\EloquentQuestionsRepository::surveys()
I notice the error mentions EloquentQuestionsRepository but I have added no methods in there so it's just an empty class:
class EloquentQuestionsRepository extends EloquentBaseRepository implements QuestionsRepository
{
}
QuestionRepository:
interface QuestionsRepository extends BaseRepository
{
}
As explained in the response to the main post - the constructor resolves the QuestionsRepository to instance of EloquentQuestionsRepository, which by the look of it is not what the store method needs.
What I would probably do is to make call to create method directly on the model and remove constructor all together - that is unless you need the instance of QuestionsRepository anywhere else in your controller:
public function store(Request $request)
{
$question = Question::create($request->all());
$question->surveys()->attach($request->surveys);
...
}
Also - I'm not sure passing $request->all() is the best thing to do - I'd probably use $request->only(...) or $request->all(...) specifying which items you want to get from the request rather than passing everything from the request to the create method.
On the other note - you could also use Form Request, which would validate data for your before passing it to the store method.
https://laravel.com/docs/5.5/validation#form-request-validation
I have a simple form, one of the fields is 'resource'. I have an Item model which has many Resources. I'm trying to save both the Item and it's Resource from my form.
Item.php:
public function resource()
{
return $this->hasMany('App\Resource');
}
public function addResource(Resource $resource)
{
return $this->resource->save($resource);
}
Resource.php:
public function item()
{
return $this->belongsTo('App\Item');
}
My save method in ItemsController:
public function store(CreateItemRequest $request)
{
//get and save Item
$item = new Item($request->all());
Auth::user()->item()->save($item);
//get and save Resource
$resource = new Resource(array($request->input('resource')));
$item->addResource($resource);
return view('items.index');
}
When calling addResource on the Item model, I get this error:
BadMethodCallException in Macroable.php line 81:
Method save does not exist.
in Macroable.php line 81
at Collection->__call('save', array(object(Resource))) in Item.php line 41
at Item->addResource(object(Resource)) in ItemsController.php line 73
at ItemsController->store(object(CreateItemRequest))
at call_user_func_array(array(object(ItemsController), 'store'), array(object(CreateItemRequest))) in Controller.php line 76
I've been stuck on this for way too long! Any help would be MUCH appreciated. I'm sure it's a simple newbie mistake...
Your addResource() method should look like this:
public function addResource(Resource $resource)
{
$this->resource()->attach($resource->id);
}
The property $this->resource will be resolved to an actual instance of a related model. If no models have yet been related it will evaluate to null. The method $this->resource() will actually return the type of relationship that exists between the models (in this case, it should return Illuminate\Database\Eloquent\Relations\HasMany).
I am wanting to validate a resource controller in Laravel, so that the user can only access clinic.show if they're the owner of said clinic.
I correctly validated this using the following:
public function show($id)
{
if (Clinic::where('id', $id)->where('user_id', Auth::id())->exists()) {
return View::make('clinic.show', ['clinic' => Clinic::where('id', $id)
->first()]);
} else {
abort(401, 'Unauthorized action.');
}
}
However, I believe this is bad practice and I should be using the Form Request feature within Laravel.
I have created a ShowClinicFormRequest.php and added the following code:
public function authorize()
{
$clinicId = $this->route('clinic');
return Clinic::where('id', $clinicId)
->where('user_id', Auth::id())
->exists();
}
And within the show function -
public function show($id, ShowClinicFormRequest $request)
{
return View::make('clinic.show', ['clinic' => Clinic::where('id', $id)->first()]);
}
However, the error that I am getting is:
ReflectionException in RouteDependencyResolverTrait.php line 53: Class
App\Http\Controllers\ShowClinicFormRequest does not exist
It obviously doesn't exist within that directory because it isn't a controller.
Any help would be greatly appreciated.
I believe your form request is located in the App\Http\Requests namespace so you need to import the class or use explicitly:
use App\Http\Requests\ShowClinicFormRequest;
or just
public function show($id, \App\Http\Requests\ShowClinicFormRequest $request)
{}
You might also to take a look at filters or middlewares.
I have a laravel model which uses ardent/eloquent. I am trying to set up tests for the controller in particular, storing a new model that uses the ardent model.
The method works in the app but I'm having trouble with my tests
I'm having problems working out how to mock the calls this method makes.
My controllers set up and the method in question is this one:
use golfmanager\service\creator\TicketCreatorInterface;
//controller manages the ticket books
class BooksController extends BaseController {
/**
* Book Repository
*
* #var Book
*/
protected $book;
protected $ticket;
public function __construct(Book $book, TicketCreatorInterface $ticket)
{
$this->book = $book;
$this->ticket = $ticket;
}
public function store()
{
$input = Input::all();
$result = $this->book->save();
if ($result) {
//if book created then create tickets
$this->ticket->createTicket($input, $this->book);
return Redirect::route('books.index');
}
return Redirect::route('books.create')
->withInput()
->withArdentErrors()
->with('message', 'There were validation errors.');
}
And the methods used by the interface (TicketCreator):
public function createTicket($input, $book) {
//dd($input);
$counter = $input['start_number'];
while($counter <= $input['end_number']) {
$ticketDetails = array(
'ticketnumber'=>$counter,
'status'=>'unused',
'active'=>1
);
$this->ticket->create($ticketDetails)->save();
$this->ticket->book()->associate($book)->save();
$counter = $counter+1;
}
return $counter;
}
My test is as follows:
use Mockery as m;
use Way\Tests\Factory;
class BooksTest extends TestCase {
public function __construct()
{
$this->mock = m::mock('Ardent', 'Book');
$this->collection = m::mock('Illuminate\Database\Eloquent\Collection')->shouldDeferMissing();
}
public function setUp()
{
parent::setUp();
$this->attributes = Factory::book(['id' => 1, 'assigned_date'=> '20/11/2013']);
$this->app->instance('Book', $this->mock);
}
public function testStore()
{
Input::replace($input = ['start_number'=>1000, 'end_number'=>1010, 'assigned_date'=>'20/11/2013']);
$this->mock->shouldReceive('save')->once()->andReturn(true);
$this->ticket->shouldReceive('createTicket')->once()->with($input, $this->mock)->andReturn(true);
//with($input);
//$this->validate(true);
$this->call('POST', 'books');
$this->assertRedirectedToRoute('books.index');
}
Currently I get an error:
No matching handler found for Book::save()
Is this being thrown because the book model doesnt contain a save method? If it is how do I mock the model correctly. I don't want it to touch the database (although it could if it has to).
Is it the multiple saves in the createTicket method?
Still learning how to set up tests correctly - slowly getting there but not enough knowledge yet.
If I change the name of the method in shouldReceive to say 'store' it still comes up with the save() error message.
Update:
I have isolated part of the problem to the createTicket call. I've changed my testStore test and updated as above.
My error with this current test is: Undefined index: start_number.
If I remove the call to createTicket in the controller method I don't get an error. I tried using Input::replace to replace the input from a form but appears not getting through to my function
How can I simulate a form input in the mocked objects?
Thanks