5

I'm building a Laravel 4.2 app and I'm using Creolab's Modules package. It's an app for managing company trainings, so my module is called Trainings. All works well except saving newly created trainings. The error I receive when I submit the Create New form is:

Call to undefined method Roche\Trainings\Facades\TrainingFacade::save()

enter image description here

These are my TrainingsController, Training Model, TrainingFacade, Trainings Service Provider and routes. Nothing I try seems to fix it.

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
Томица Кораћ
  • 2,542
  • 7
  • 35
  • 57
  • well you have given no info. Please paste your code here and paste the part that errors; give us the code where the request bumps into error. – Mostafa Talebi Nov 07 '14 at 11:16
  • 1
    What exactly are you trying to accomplish here with a facade? You would want to be calling eloquents `save()` method on a record that you have modified. Also, I believe `getFacadeAccessor()` should return the class name as a string, not an instance. – Supericy Nov 07 '14 at 11:38
  • @MostafaTalebi can you please tell me what more info you need? I provided my Controller, Model, Facade, Service provider and routes. The `if($this->training->save())` line in the Controller's postCreate method returns the error. – Томица Кораћ Nov 07 '14 at 15:06
  • @Supericy I'm just trying to save the data from the form in the database. I don't think I understand what record am I modifying when I'm creating a new training. About the `getFacadeAccessor()` I only used the code shown in this example here: https://github.com/bstrahija/laravel-modules-example/blob/master/app/modules/content/facades/EntryFacade.php – Томица Кораћ Nov 07 '14 at 15:12
  • But why do you need a custom Facade for that? Using the Model class directly should be perfectly fine. – lukasgeiter Nov 08 '14 at 09:22
  • @lukasgeiter I'm aware of that, and it actually works if I add `use \Namespace\Models\Training` to my controller. But I would still want to know why this code doesn't work. What's wrong in the current configuration? – Томица Кораћ Nov 08 '14 at 09:30
  • I suppose something with having an alias the same name as a model is the problem. If you rename your alias, does it work? – lukasgeiter Nov 08 '14 at 09:35
  • Then I'm getting this error: `Class Training does not exist`. – Томица Кораћ Nov 08 '14 at 09:55
  • @ТомицаКораћ I mean rename the alias where you use it as well... – lukasgeiter Nov 08 '14 at 19:55

1 Answers1

7

You don't need to change your facade alias here, but you have other error here.

In your AdminTrainingsController you want to use Training model so you import Training before your class definition this way:

use Training;

but model Training is not in root namespace, in root namespace there is TrainingFacade because you probably define it in your app.php file this way:

'Training' => 'Roche\Trainings\Facades\TrainingFacade',

That's ok, you don't need to change this facade alias.

So now, Laravel inject into your constructor not Training model but TrainingFacade (because Training in root namespace is alias for TrainingFacade).

What you need here is importing correct namespace for your Training model.

When we look at your Training model class we see the code is:

<?php namespace Roche\Trainings\Models;

class Training extends \Eloquent {

protected $guarded = array('id');

}

so it's in Roche\Trainings\Models namespace.

So to make it work in AdminTrainingsController you need to change:

use Training;

into:

use Roche\Trainings\Models\Training;

Now Laravel will inject into constructor Training model (and not TrainingFacade as it was doing).

EDIT

You could also make some tests, for example changing in your app.php your TrainingFacade alias, for example to:

    'TrainingFacade' => 'Roche\Trainings\Facades\TrainingFacade',

but if you had use Training as you had, you would get the following error:

Class Training does not exist

because there would be no Training class in global namespace now (you changed alias for facade).

And if you removed use Training; completely, you would get:

Class Roche\Trainings\Controllers\Admin\Training does not exist

because by default class is loaded from current namespace, and your AdminTrainingsController is in Roche\Trainings\Controllers\Admin namespace

I hope now everything is clear, if it's not you could also look at How to use objects from other namespaces and how to import namespaces in PHP where I explained more about namespaces

Community
  • 1
  • 1
Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
  • Marcin thank you very much for the thorough explanation. I now have two questions: 1. Why am I only getting this error when creating a new training, and not when I am updating an existing one? The code in both methods is almost the same. 2. Can you please look at my `TrainingFacade` and tell me if the code there is OK? @Supericy mentioned that a facade should return a string and not an instance. Is that correct, or is my code ok? Thanks. – Томица Кораћ Nov 10 '14 at 18:21
  • @ТомицаКораћ And where do you have update method here? I see only create method – Marcin Nabiałek Nov 10 '14 at 18:46
  • Sorry, I removed it to make my question more focused on this method only. This is actually my entire controller: http://laravel.io/bin/eDG9k . I would appreciate if you let me know if you see anything unusual. – Томица Кораћ Nov 10 '14 at 19:09
  • @ТомицаКораћ This is different situation, because for other actions you use route model binding in routes. You have there `Route::model('training', 'Roche\Trainings\Models\Training');` - as you see also with full namespace. And about facades - yes, you return string here, you could look at http://stackoverflow.com/questions/25978931/how-to-create-custom-facade-in-laravel-4/25979624 – Marcin Nabiałek Nov 10 '14 at 19:32
  • Aaah, I get it now! This was really confusing me. Only now I realize why only `postCreate()` wasn't working. Marcin you're a star! Thank you so much for having so much patience. My problem here is, beside I'm a beginner, I'm combining https://github.com/bstrahija/laravel-modules-example and https://github.com/andrewelkins/Laravel-4-Bootstrap-Starter-Site, and the differences confuse me. Your links will help me a lot. Thanks again buddy! – Томица Кораћ Nov 10 '14 at 19:54
  • @ТомицаКораћ Glad I could help, I'm also Laravel beginner :) – Marcin Nabiałek Nov 10 '14 at 19:59