laravel 'class not found' error on production - php

Slightly odd one here.
I have Persons and Actions. Persons can have many Actions, while each Action belongs to only one Person. I'm using Chumper's Datatables to display a list of people, including a count of their actions.
Since migrating to a production (forge) server, I'm getting
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_ERROR)
Class 'action' not found
when calling the datatable. The error shown
/­vendor/­laravel/­framework/­src/­Illuminate/­Database/­Eloquent/­Model.php:721
public function hasOne($related, $foreignKey = null, $localKey = null)
{
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
$localKey = $localKey ?: $this->getKeyName();
suggests it's a problem with my hasMany relationship:
# /models/Person.php
class Person extends Eloquent {
public function actions()
{
return $this->hasMany('Action');
}
# /models/Action.php
class Action extends Eloquent {
public function person()
{
return $this->belongsTo('Person', 'person_id');
}
I assume these are fine, however, as it all works locally. Datatables also works fine elsewhere, calling through other items and their related actions with no trouble.
I've tried composer dump-autoload and artisan dump-autoload on the production server, to no avail. The deployment script on forge is below:
git pull origin master
composer install
php artisan migrate --env=production
I can't tell if it's a config issue, a database issue, a code issue or something else entirely. I've been back through the many similar questions but nothing's jumped out. Any help much appreciated.

for who may have the same problem, triple check the casing of your model! I had it wrong, that's why locally on mac was working but not on the server

So I think I'd borked this one myself.
I'd been lazy and left function datatablePersons() in PersonsController.php using an old 'count' method, relying on long-defunct relationships (that caused n+1, so had to be binned), hence it wobbling over an actions class whenever that relationship was called upon.
Datatable functions in other controllers (with a cleaner 'count' method) work fine, so I've just rewritten datatablePersons() to use the same method.
I've not quite got the query right (in eloquent, at least) yet - see this question here: mysql join ON and AND to laravel eloquent - but the class not found error has certainly gone away.
I'm (massively) guessing that the classmap on the local machine hadn't been flushed since whatever was removed was removed, while the production machine is rebuilt every push, hence the disparity...?
Either way, it's no longer an issue.

Related

Yii2 $model->_attributes assignment does not work in new version

I inherited a project that was created with Yii2, ver. 2.0.4, with the task to update said project to a more current version of Yii2 (2.0.15) because of the incompatibility of the older one with PHP 7.2+.
I noticed that there is a lot of use of assigning arrays to a model:
$model->_attributes = $array;
With the new version this results in an exception
'yii\base\UnknownPropertyException' with message 'Setting unknown property: app\models\model::_attributes'
For the time being I created a workaround with the following function:
function customSetAttributes(&$model, $array) {
foreach($model->attributeLabels() as $model_key => $model_label) {
if(!isset($array[$model_key])) continue;
$model->$model_key = $array[$model_key];
}
}
Also, the getter function now has a similar issue.
What I would like to know:
Was this type of assignment never intended in the first place (and I just haven't found the previous developer's code that enables it)? I skimmed over the Yii2 changelog but didn't notice anything related.
Is there a way to "salvage" the previous behaviour so I don't have to replace each occurence with my workaround function?
ActiveRecord::$_attributes was always private and never should be used in this way. I guess that previous developer edited framework core files in vendor directory and make this property protected/public.
You may try to emulate this behavior by creating virtual attribute using getter and setter:
public function get_attributes() {
return $this->getAttributes();
}
public function set_attributes($values) {
$this->setAttributes($values, false);
}
But this will not always work and it is more like an ugly hack to make crappy code work. I strongly suggest to fix code to use setAttributes() instead of _attributes.
Also you should compare yii2 package from vendor directory with source from https://github.com/yiisoft/yii2-framework/releases/tag/2.0.4 - you may find more places where core was edited.

Testing Laravel Service Providers

I'm (we're) creating a package that acts as a core component for our future CMS and of course that package needs some unit tests.
When the package registeres, the first thing it does is set the back/frontend context like this:
class FoundationServiceProvider extends ServiceProvider
{
// ... stuff ...
public function register()
{
// Switch the context.
// Url's containing '/admin' will get the backend context
// all other urls will get the frontend context.
$this->app['build.context'] = request()->segment(1) === 'admin'
? Context::BACKEND
: Context::FRONTEND;
}
}
So when I visit the /admin url, the app('build.context') variable will be set to backend otherwise it will be set to `frontend.
To test this I've created the following test:
class ServiceProviderTest extends \TestCase
{
public function test_that_we_get_the_backend_context()
{
$this->visit('admin');
$this->assertEquals(Context::BACKEND, app('build.context'));
}
}
When I'm running the code in the browser (navigating to /admin) the context will get picked up and calling app('build.context') will return backend, but when running this test, I always get 'frontend'.
Is there something I did not notice or some incorrect code while using phpunit?
Thanks in advance
Well, this is a tricky situation. As I understand it, laravel initiates two instances of the framework when running tests - one that is running the tests and another that is being manipulated through instructions. You can see it in tests/TestCase.php file.
So in your case you are manipulating one instance, but checking the context of another (the one that did not visit /admin and is just running the tests). I don't know if there's a way to access the manipulated instance directly - there's nothing helpful in documentation on this issue.
One workaround would be to create a route just for testing purposes, something like /admin/test_context, which would output the current context, and the check it with
$this->visit('admin/test_context')->see(Context::BACKEND);
Not too elegant, but that should work. Otherwise, look around in laravel, maybe you will find some undocumented feature.

Declaration of Child method should be compatible to Parent Method

got this error on Yii2. I dont know what exactly the problem is. I just migrate my source code from Windows to Mac OS. I tried cloning my whole project still the error appears.
Declaration of common\models\Product::getAttributes() should be compatible with yii\base\Model::getAttributes($names = NULL, $except = Array)
These are the things i tried:
Clone the whole project to Mac OS. - error above exists.
Clone the whole project to another windows machine.-the project is running well.
I am using yii2 in this project.
As you can see from the error message, you overrided yii\base\Model getAttributes() method. common\models\Product is extended from yii\db\ActiveRecord and ActiveRecord is extended from yii\base\Model.
If you really want to override this method, list all parameters (see here), it's easier to do with help of IDE. And by the way this is PHP feature and has nothing to do with OS or Yii2.
If it is your custom method for another purposes, you need to rename it in order to resolve conflict.
Your method must accept the same parameters ($names = NULL, $except = Array)

"User" model broken after Laravel 4.1 upgrade

I have upgraded Laravel from 4.0 to 4.1 recently in a few instances. Today I did the upgrade in yet another instance and found out that there is something wrong with the User model. The models/User.php file is still there, but I don't think it is used by Laravel anymore. My question is: why?
To demonstrate the issue, I have created the following entries in my routes.php:
Route::get('test1', function()
{
$course = Course::find(4);
return ($course->users()->first());
});
Route::get('test2', function()
{
$user = User::find(22);
return ($user->courses()->first());
});
Both these entries are correct regarding syntax and the database object (course with id 4 exists and user with id 22 exists). My Course.php model has the following:
public function users()
{
return $this->belongsToMany('User')->withPivot('participant_role')->withTimestamps();
}
And my User.php has a corresponding entry:
public function courses()
{
return $this->belongsToMany('Course')->withPivot('participant_role')->withTimestamps();
}
Now if I launch the first URL, /test1, I get a working JSON entry as a result. As expected.
With the second URL, /test2 however I get an error message:
BadMethodCallException
Call to undefined method Illuminate\Database\Query\Builder::courses()
open: /home/simoa/laravelapps/clientname/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php `
I think there is something wrong here. Why is my Laravel instance trying to call the courses() method from the Illuminate\Database\Query\Builder class? That isn't normal, right?
As I said earlier, everything else works perfectly, except things to do with the User model.
The issue was caused by an invalid entry in the file vendor/composer/autoload_classmap.php.
For some reason during the 4.1 upgrade (probably running the command: composer update) the entry for 'User' => $baseDir . '/app/models/User.php' has turned into 'User' => $baseDir . '/app/models/old_User.php' in that file.
I did have an old backup/dev file called old_User.phpin my models directory and for some reason, it seems, composer has mapped User class to that file.
Solution: delete old_User.php and re-run composer update.
try running php artisan clear-compiled and then php artisan optimize

PHP activerecord exception : Base table or view not found

I am trying out php active record, it's a great ORM, however I am at a standstill.
I have looked around google, blogs, phpactiverecord documentation as well as statckoverflow for days but have not been able to come across a suitable solution to this problem.
I am able to carry out the basic CRUD (insert,fetch, modify and delete) operations however as soon as i validate an object property using a static $validates_uniqueness_of filter, i get
Fatal error: Uncaught exception 'ActiveRecord\DatabaseException'
With message
exception 'PDOException' with message 'SQLSTATE[42S02]: Base table or
view not found: 1146 Table 'test_ar.models' doesn't exist' in
C:\wamp\www\test_AR\AR\lib\Connection.php on line 325
Here is the code i used in full.
<?php
$path_to_AR = "AR/";
include $path_to_AR . "activerecord.php";
ActiveRecord\Config::initialize(function($cfg) {
$cfg->set_model_directory('model');
$cfg->set_connections(
array(
'development' => 'mysql://root:asdf#localhost/test_ar',
'test' => 'mysql://username:password#localhost/test_database_name',
'production' => 'mysql://username:password#localhost/production_database_name'
)
);
});
/*
class user extends ActiveRecord\Model
{
static $validates_presence_of = array(array('username', 'message' => 'Please supply a username')); //this works just fine
static $validates_uniqueness_of = array(array('username'));//this line causes the PDO exception
}
*/
$user = new user();
user::create((array('username'=>'mike','password'=>'test','created'=>time())));
$user::create(array('username'=>'mike')); //cannot even reach this line because of the exeption
References i have tried/looked at
https://github.com/kla/php-activerecord/issues/274 (though i don't really understand what's going on there)
http://www.phpactiverecord.org/projects/main/wiki/Validations#validates_uniqueness_of
http:// blog.felho.hu/what-is-new-in-php-53-part-2-late-static-binding.html
as well as many others.
Platform and php version
I am using php 5.3.4 and using nightly build (May 8 2013) I have almost failed to get my head around this. Please advise on how to correct this.
This has been solved by the question author:
After discussing it with a few developers on github. It seems this is a bug.
The work around was to create a custom validator in the model
public function validate() {
if ($this->is_new_record() && static::exists(array('conditions' => array('username' => $this->username)))) {
$this->errors->add('username', 'This username is already taken');
}
}
I had this error crop up today in a custom application, not Drupal.
my error was the exact same one.
however the issue was that I created the application on a windows server, then moved it to a linux based server.
apparently during creation the windows based application ran just fine, but threw the error mentioned after move to Linux.
THE ISSUE WAS:
--a database table that was created with a capital litter such as statePages... when it was created it was renamed to statepages without the camel case letter.
once I went into the application and where the app connected and drew information from the database, I removed the mismatch capital letter, and the application found the database table just fine and work like expected.
hope this helps someone else.

Categories