I have a folder named 'Validators' inside my 'Models' folder that contains the validation files for creating new records. I have not had problems in the past putting this folder inside the 'Models' folder within my Laravel PHP project but for some odd reason when I try to create/store new records, I keep getting a Class 'Models\Validators\Stone' not found error.
Controller:
<?php
use Acme\repositories\StoneRepository;
use Acme\repositories\PhotoRepository;
use Models\Stone;
use Models\Stone_Photo;
/* 'Validators' folder inside 'Models' folder */
use Models\Validators as Validators;
class StonesController extends BaseController {
/*The stone model */
protected $stone;
/*The stone_photo model */
protected $stone_photo;
protected $layout = 'layouts.master';
/* This is the function that is currently being called */
public function store()
{
$input = \Input::all();
/* This is where the error occurs on this line below */
$validation = new Validators\Stone;
/* Validation code here */
}
}
Stone Validator (app\models\validators\stone.php):
<?php namespace Models\Validators;
class Stone extends Validator {
/* The rules for validating the input */
public static $rules = array(
'stone_name' => 'required',
'stone_description' => 'max:255',
);
}
I have tried running 'php artisan dump-autoload' but that still does not change anything. This implementation has worked for me in the past but for some reason I keep getting this error and I don't know why. Any help is greatly appreciated!
Related
I want to develop a plugin that extends RainLab.Blog in October CMS.
My plugin's database appears in the SQL database and backend form that takes the new input while editing a blog post renders just fine, but the issue appears when trying to save the changes to SQL, wheree they appear NULL:
"Method OleMol\BlogExtensions\Models\Extension::__toString() must not throw an exception, caught Illuminate\Database\Eloquent\JsonEncodingException: Error encoding model [OleMol\BlogExtensions\Models\Extension] with ID [2] to JSON: Recursion detected" on line 0 of C:\xampp\htdocs\vendor\laravel\framework\src\Illuminate\Support\Str.php
This seems to be a Laravel problem and it's the first time I'm using October in a professional project.
Initially, I tried to use a table with a bunch of columns, but for troubleshooting, I have stripped it down to one custom column until I can find an answer.
I am trying to follow along to this video tutorial, but extending RainLab.Blog instead of RainLab.User.
cd C:\xampp\htdocs
php artisan create:plugin OleMol.BlogExtensions
plugins\olemol\blogextensions\Plugin.php
<?php namespace OleMol\BlogExtensions;
use Backend;
use System\Classes\PluginBase;
use RainLab\Blog\Models\Post as PostModel;
use RainLab\Blog\Controllers\Posts as PostsController;
use OleMol\BlogExtensions\Models\Extension as ExtensionModel;
/**
* BlogExtensions Plugin Information File
*/
class Plugin extends PluginBase {
/* RainLab.Blog is a dependency for this plugin. */
public $require = [ 'RainLab.Blog' ];
public function boot() {
PostModel::extend(function($model) {
$model -> hasOne[ 'blogextension' ] = [ 'OleMol\BlogExtensions\Models\Extension' ];
});
PostsController::extendFormFields(function($form, $model, $context) {
//Only extend this controller if the model is a post.
if (!$model instanceof PostModel) { return; }
//Don't create an extension to a model that does not exist.
if (!$model -> exists) { return; }
//Ensure that the post always has an extension before adding fields.
ExtensionModel::getFromPost($model);
$form -> addTabFields([ 'blogextension[business_name ]' => [ 'label' => 'Business Name', 'tab' => 'Business' ]);
});
}
} }
plugins\olemol\blogextensions\updates\version.yaml
1.0.1:
- First version of BlogExtensions
1.0.2:
- create_business_table.php
plugins\olemol\blogextensions\updates\create_business_table.php
<?php namespace OleMol\BlogExtensions\Updates;
use Schema;
use October\Rain\Database\Schema\Blueprint;
use October\Rain\Database\Updates\Migration;
class CreateBusinessTable extends Migration {
public function up() {
Schema::create('olemol_blogextensions_business', function (Blueprint $table) {
$table -> engine = 'InnoDB';
$table -> increments('id');
$table -> integer('post_id') -> unsigned() -> index();
/*
* This always ends up as NULL!
* (Or default value in case it's not nullable).
*/
$table -> string('business_name') -> nullable();
$table -> timestamps();
});
}
public function down() {
Schema::dropIfExists('olemol_blogextensions_business');
}
}
plugins\olemol\blogextensions\models\Extension.php
<?php namespace OleMol\BlogExtensions\Models;
use Model;
/**
* Extension Model
*/
class Extension extends Model {
use \October\Rain\Database\Traits\Validation;
/**
* #var string table associated with the model
*/
public $table = 'olemol_blogextensions_business';
/**
* #var array dates attributes that should be mutated to dates
*/
protected $dates = [ 'created_at', 'updated_at' ];
public $belongsTo = [ 'post' => [ 'RainLab\Blog\Models\Post' ]];
/* Helper-function to ensure that post always has an extension. */
public static function getFromPost($post) {
if ($post -> extension) { return $post -> extension; }
$extension = new static;
$extension -> post = $post;
$extension -> save();
$post -> extension = $extension;
return $extension;
}
}
I have included the code I think is necessary. The files still contain auto-generated empty blocks which are omitted.
php artisan plugin:refresh OleMol.BlogExtensions
php artisan project:sync
php artisan october:migrate
I'm on a tight schedule and I feel like I'm lost at this point.
Please reach out if more information is needed.
I would appreciate any help coming my way.
I think in your code Extension.php-> getFromPost method need some corrections
// plugins\olemol\blogextensions\models\Extension.php: getFromPost method:
$post->extension = $extension;
It should be: blogextension instead of only extension
$post->blogextension = $extension;
// ^ HERE
You need to specify your hasOne relation name there
if any doubt please comment
I would like to create a component in yii2 that can be accessed throughout the web application but only create one instance and be able to retrieve that instance wherever needed.
namespace app\components;
use yii;
use yii\base\Object;
class ContentManagerComponent extends Object
{
public function init(){
parent::init();
}
public function toBeUsed (){
return 'some variable';
}
}
Then I want to be able to call the component in other parts of the web application, like in the controllers.
namespace app\Controllers;
use yii;
use app\controllers\
class SomeController extends Controller {
public function actionDoSomething(){
$contentComponent = Yii::$app->content;
$someVariable = $contentComponent->toBeUsed()
return $this->render( 'someView',[
'variable' => $someVariable,
]
}
}
I have also put the component in the web.php file.
$config = [
'components' => [
'content' => [
'class' => 'app\components\ContentManagerComponent',
],
],
],
What I'm ending up with is phpstorm telling me that the class doesn't exist. I would also like to have intelisense like the other components do in the application.
intelisense:
noIntele:
update:#
I was able to get intelisense working by adding the this line as suggested by the answer below. /** #var ContentComponent $contentManager */
However I got tired of always typing that out above each time I wanted to use the Content Component. So I created a function in the base class of the components I was needing Content Component that return the Continent Component using the Yii::app->content method. Above the function that would return the Content Component I added the comment that it would return ContentComponent and the class of the ContentComponent. Now in order for me to use the component with intelisense working. All I would have to do is $this->getContentComponent. Php storm would be able to identify that the content component was of the class returned. Bellow is an example.
class BaseClass extends object
{
/**
* #return ContentComponent
*/
function getContentComponent () {
$contentComponent = Yii::app->content;
return $contentComponent
}
}
class SomeClass extends BaseClass
public function someFunction () {
$contentComponent = $this->getContentComponent;
}
PHPStorm don't recognize your custom component because they are created dynamically on framework load and attached to Yii::$app on runtime, That's why PHPStorm don't recognize your custom components. So until someone will develop an intelligent plugin for IDEs like PHPStorm, you will have to make some tweaks to achieve your goals.
You have 2 options:
Create a new Yii.php file (in root dir) for reference with all the
necessary docs and this will tell PHPStorm in the entire project
about your components (I putted here a full example, if you want to create components which available only for console/web/both) look at * #property ContentManagerComponent $content (More read - credit to samdark Alexander Makarov, one of Yii core contributors):
<?php
use app\components\ContentManagerComponent;
use yii\BaseYii;
/**
* Class Yii
* Yii bootstrap file.
* Used for enhanced IDE code autocompletion.
*/
class Yii extends BaseYii
{
/**
* #var BaseApplication|WebApplication|ConsoleApplication the application instance
*/
public static $app;
}
/**
* Class BaseApplication
* Used for properties that are identical for both WebApplication and ConsoleApplication
*
* #property ContentManagerComponent $content
*/
abstract class BaseApplication extends yii\base\Application
{
}
/**
* Class WebApplication
* Include only Web application related components here
*
*/
class WebApplication extends yii\web\Application
{
}
/**
* Class ConsoleApplication
* Include only Console application related components here
*/
class ConsoleApplication extends yii\console\Application
{
}
Create a PHP doc everywhere you want to use your component which
will tell PHPStorm that your variable is instance of the component:
public function actionDoSomething()
{
/** #var ContentManagerComponent $contentComponent */
$contentComponent = Yii::$app->content;
$someVariable = $contentComponent->toBeUsed();
return $this->render('someView', [
'variable' => $someVariable,
]);
}
As you can see option 1 is a solution provided by one of the core contributors of the Yii framework, so I assumes that this suppose to be the right choice for now (until there will be native support by JetBrains or any plugin)
Once you have declared your content component in you config files
$config = [
'components' => [
'content' => [
'class' => 'app\components\ContentManagerComponent',
],
],
],
then you can refer tor the component using
Yii::$app->content
eg
Yii::$app->content->yourMethod();
eventually add use Yii; or refer using \Yii::$app->content
I use the following method for intellisense.
1.Set your components inside config.
$config = [
'components' => [
'content' => [
'class' => 'app\components\ContentManagerComponent',
],
'content2' => [
'class' => 'app\components\ContentManagerComponent2',
],
],
],
2.Have an AppComponents trait, documenting all instances that your $app has. I like to have it inside components/ directory.
<?php
namespace app\components;
/**
* Trait AppComponents
* #package app\components
*
* #property ContentManagerComponent1 $content
* #property ContentManagerComponent2 $content2
*/
trait AppComponents {}
3.Return the Yii::$app your own way. Trick the editor into believing that AppComponents may be returned.
<?php
namespace app\controllers;
use frontend\components\AppComponents;
use yii\rest\Controller;
class SiteController extends Controller {
/**
* #return \yii\web\Application|AppComponents
*/
public static function app() {
return \Yii::$app;
}
}
Now you can use SiteController::app()->content with intellisense. You can have a nicer Root class, and replace \Yii::$app with Root::app(). All Controllers may inherit from the Root class. You can also use self::app() when coding inside the extended Controllers.
I have a controller in components/test/test/controllers folder, called MyController. If I set the namespace as "namespace app\components\test\test", and then I try to call the controller if says "Page Not Found".
I have been reading and I know that by default Yii2 sets namespace for controllers to "app\controllers".
Also know that you can change namespace for all controllers from config:
'controllerNamespace' => 'app\\components\test...'
But I just wanted to change for one controller not for all. Something similar to modules, there you can do:
$this->controllerNamespace = 'app\modules\test\test';
I just found there is something called "controllerMap", maybe this could be a solution? any ideas?
Example
I have created inside "components" (basic template) a controller LocationController with this content:
namespace app\components;
use yii\web\Controller;
class LocationController extends Controller {
public function actionAdd() {
return "hola1";
}
public function actionRemove() {
return "hola2";
}
}
When I created a link Yii::$app->urlManager->createAbsoluteUrl("location/add"); and click on it I get "Page not found" error.
UPDATE
I have found that is possible to add classes to classMap, but not sure where to place it:
Yii::$classMap['app\components\LocationController'] = '..path.../components/LocaitonController.php'
Maybe this could do the trick?
About your "Not found" problem, your controllerNamespace and namespace must have the full path of the controller, in your case:
app\modules\test\test\controllers
Now,to change the path for a single controller I can only think of creating a Module inside your app (like you mentioned):
<?php
namespace app\modules\test\test;
/**
* module definition class
*/
class Module extends \yii\base\Module
{
/**
* #inheritdoc
*/
public $controllerNamespace = 'app\modules\test\test\controllers';
/**
* #inheritdoc
*/
public function init()
{
parent::init();
// custom initialization code goes here
}
}
And add in your config the module:
$config = [
...
'modules' => [
'module' => 'app\modules\test\test\Module'
]
];
EDIT
You can also add in your config:
$config = [
...
'controllerMap' => [
'location' => 'app\components\LocationController',
],
];
I've one module -> users.
->modules
->users
->controllers
->models
->views
->Users.php
I created one 'config.php' inside 'config' folder of 'users' modules.
->modules
->users
->config
->config.php
->controllers
-> List of Controllers
->models
-> List of models
->views
-> List of Views
->Users.php
And, i gave directory path of config.php in init() method of Users.php, as
modules/users/Users.php
<?php
namespace app\modules\users;
class Users extends \yii\base\Module
{
public $controllerNamespace = 'app\modules\users\controllers';
public $commonModel = 'app\modules\users\models\Users';
public function init()
{
parent::init();
\Yii::configure($this,require(__DIR__.'/config/config.php'));
}
}
But, it is giving error like
PHP Warning – yii\base\ErrorException
"Invalid argument supplied for
foreach()".
Screenshot
I am taking reference from Yii2.0 Guide to include a path inside init() method.
Please help me to rectify this issue.
Thanks.
From what I can see, you're passing in the PHP code to your config file, instead of passing in a configuration array
Instead of this...
\Yii::configure($this, require(__DIR__.'/config/config.php'));
Try doing this...
$config = require(__DIR__.'/config/config.php');
\Yii::configure($this, $config);
In your config.php file you should be returning an array, if you're using the basic-app config file and adding to that then it should be set up like this already
The problem comes from the configuration file. The configureation file must returns an array. Make sure that the config file is as follows:
<?php
$config = [
'name1' => 'value1',
'name2' => [/* something here */],
];
return $config;
you edit file model and delete code:
/**
* #inheritdoc
* #return DriverSearch the active query used by this AR class.
*/
public static function find()
{
return new DriverSearch(get_called_class());
}
I'm trying to seed my DB but I have a problem when I use modelName::create() or $modelName->save().
I have this kind of error
{"error":{"type":"Symfony\Component\Debug\Exception\FatalErrorException","message":"Call to undefined method Doc::save()","file":"/Applications/MAMP/htdocs/Doc_project/app/database/seeds/DatabaseSeeder.php","line":45}
or
Call to undefined method Doc::create()
but i dont know why.
My Model :
class Doc extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'doc';
protected $fillable = array('creators_name', 'type_document', 'title', 'description');
public function steps(){
return this->hasMany('Step')
}
public function tags(){
return this->belongsToMany('Tag', 'doc_tag', 'id_doc', 'id_tag')
}
}
My Seeder :
class DatabaseSeeder extends Seeder {
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Eloquent::unguard();
$this->call('DocAppSeeder');
$this->command->info('Doc app seeds finished.'); // show information in the command lin }
}
}
class DocAppSeeder extends Seeder {
public function run(){
DB::table('doc')->delete();
DB::table('step')->delete();
DB::table('tag')->delete();
DB::table('doc_tag')->delete();
/* DB::table('doc')->insert(array(
'creators_name' => 'Alexis',
'type_document' => 'Solution',
'title' => 'NoAD Printer',
'description' => 'Installation imprimante en NoAd'
));*/
$doc = new Doc;
$doc->creators_name = 'Alexis';
$doc->type_document = 'Solution';
$doc->title = 'NoAD Printer';
$doc->description = 'Installation imprimante en NoAd';
$doc->save();
/*$docTest = Doc::create(array(
'creators_name' => 'Alexis',
'type_document' => 'Solution',
'title' => 'NoAD Printer',
'description' => 'Installation imprimante en NoAd'
));
}
}
I try with DB::Table(...)->insert(...)it works, but I can't use it because I need to get some information on each object
Someone have an idea?
Thank you
It looks like PHP is using a different global level Doc class than the one you think it is. Maybe for a facade or alias (self link, contains details instructions on how to debug facade issues)?
Regardless, the best course of action is to see where PHP thinks this class is. In you seeder, right before save, include the following debugging code
$r = new ReflectionClass('Doc');
var_dump(
$r->getFilename()
);
var_dump(
$r->getName()
);
This will tell you the full-name of the class (if it's an alias) and where the class is defined. My guess is the class you think is Doc is not your Eloquent model, and is, in fact, a different class.
Based on your comments below, it sounds like someone's defined a class named Doc in
/Applications/MAMP/htdocs/Doc_project/app/database/migrations/2014_10_12_201016_doc.php
This isn't normal -- although it's easy to see how it might have happened. You probably used the artisan command to create a migration like this
php artisan migrate:make doc
By not using the more explicate form
php artisan migrate:make create_doc_table
You inadvertently create a migration class with the same name as your model. Try recreating this migration with a less specific name, and you should be all set.
Check your migration file -
Rollback the migration, create a fresh version of migration file and proceed.
It usually happens with artisans when used to create a migration.
For me, i rollback the migration and recrested the migration with another name and it works.