So i am new to MVC and im trying to understand how this works.
As i understood this is how the autoloder should open
http://www.example.com/controller/action.
I have this is my indexAction
public function indexAction()
{
$this->view->setVars([
'name' => 'Stefan',
]);
}
And this in my index.phtml
<h1>Hello <?php echo $name ?></h1>
But when i call my local-host this is how he tried to open it.
Page not found: \Mvc\ControllerInterface\IndexControllerInterface::IndexAction
Here is my full autoloader
<?php
// simple autoloader
spl_autoload_register(function ($className)
{
if (substr($className, 0, 4) !== 'Mvc\\')
{
// not our business
return;
}
$fileName = __DIR__.'/'.str_replace('\\', DIRECTORY_SEPARATOR, substr($className, 4)).'.php';
if (file_exists($fileName))
{
include $fileName;
}
});
// get the requested url
$url = (isset($_GET['_url']) ? $_GET['_url'] : '');
$urlParts = explode('/', $url);
// build the controller class
$controllerName = (isset($urlParts[0]) && $urlParts[0] ? $urlParts[0] : 'index');
$controllerClassName = '\\Mvc\\ControllerInterface\\'.ucfirst($controllerName).'ControllerInterface';
// build the action method
$actionName = (isset($urlParts[1]) ? $urlParts[1] : 'index');
$actionMethodName = ucfirst($actionName).'Action';
//var_dump($url,$urlParts,$controllerName,$actionMethodName);
//
try {
if (!class_exists($controllerClassName)) {
throw new \Mvc\Library\NotFoundException();
}
$controller = new $controllerClassName();
if (!$controller instanceof \Mvc\Controller\ControllerInterface || !method_exists($controller, $actionMethodName)) {
throw new \Mvc\Library\NotFoundException();
}
$view = new \Mvc\Library\View(__DIR__.DIRECTORY_SEPARATOR.'views', $controllerName, $actionName);
$controller->setView($view);
$controller->$actionMethodName();
$view->render();
} catch (\Mvc\Library\NotFoundException $e) {
http_response_code(404);
echo 'Page not found: '.$controllerClassName.'::'.$actionMethodName;
} catch (\Exception $e) {
http_response_code(500);
echo 'Exception: <b>'.$e->getMessage().'</b><br><pre>'.$e->getTraceAsString().'</pre>';
}
And here is my folder structure.
I tried playing around with the folder Structure and with my xxamp httpd conf.
But nothing relly works.
What am i missing here.
There are a couple of things I can see wrong.
First you are ending $controllerClassName with "ControllerInterface" whereas your class according to your directory structure your index controller is IndexController.
Secondly when checking if an object is not an instance of a particular class you need to wrap the negated check in parenthesis e.g. if (!($controller instanceof \Mvc\Controller\ControllerInterface)){} see example 3 here http://php.net/manual/en/language.operators.type.php
I have a project leash and in JSON-RPC service I'm writing to a file in __destruct, but sometimes the config file is cleared (it look like this {"sessions":[],"users":[]}) it happen from time to time and also when I refresh the page fast before ajax request is finished, it look like the __constructor didn't finished before __destruct is called, I have code like this:
class Service {
protected $config_file;
protected $config;
const password_hash = 'h'; // function use for password on installation
const password_regex = '/([A-Za-z_][A-Za-z0-9_]*):(.*)/';
function __construct($config_file, $path) {
$this->path = $path;
$this->config_file = $config_file;
$full_path = $path . "/" . $this->config_file;
if (file_exists($full_path)) {
try {
$this->config = json_decode(file_get_contents($full_path));
} catch (Exception $e) {
$this->config = new stdClass();
}
// it had no write permission when first created while testing
if (!is_writable($full_path)) {
chmod($full_path, 0664);
}
} else {
$this->config = new stdClass();
}
if (!isset($this->config->sessions) || !is_array($this->config->sessions)) {
$this->config->sessions = array();
} else {
$this->config->sessions = array_map(function($session) {
return Session::cast($session);
}, array_filter($this->config->sessions, function($session){
return isset($session->token) && isset($session->username);
}));
}
if (!isset($this->config->users) || !is_array($this->config->sessions)) {
$this->config->users = array();
}
}
// ------------------------------------------------------------------------
function __destruct() {
$path = $this->path . "/" . $this->config_file;
$this->__write($path, json_encode($this->config));
}
I have other methods that modify config object like login that add new session to $this->config->sessions array. Here is full file
I've tried to add flag $this->corrupted that's set to true when I've get exception but it didn't fix the issue, it must be something with time of __destruct being called.
I've also try to add flag $this->safe_to_save that get set to true in last line of constructor but that also didn't work. What may be the problem?
This is an app that's intended to generate entities, allowing the end user to define the fields, and it worked like charm, until Sf 2.3 and PHP version something(don't recall the version that was running) on a debian 7. But now it's on a FreeBSD with PHP 5.4.28 and SF 2.4
It can create an entity from scratch or recreate and overwrite it with changes.. but all of a suden, the autoloader stopped (re-)loading the class after it's created. It wont be until next postback, that it actually sees the class, obviously if I don't create it again (e.g. commenting code).
So, The question is How can I force autoload of a class whose code had been written and saved to the class' php file during the request handling..?
The following code gives class not found.
/**
* Handles creation of the Doctrine Entity that will represent de Document being
* created.
*
* #param DocumentType $docDefinition The Document definition
*
* #return string Genedated Document's class shortcut notation.
*
* #throws \Exception if {#link $this->doctrineGenEntityCmd}->run() fails or throws
*/
protected function createDocumentEntity(DocumentType $docDefinition)
{
$this->log->info("Creating Document entity");
try {
list($exitCode, $out) =
$this->runCommand('generate:doctrine:entity', $this->generateEntityCmd, $docDefinition);
} catch (\Exception $exc) {
throw new \Exception(
sprintf("Can't create Document due to following: \n %s", $exc->getTraceAsString()),
null,
$exc
);
}
if (0 != $exitCode) {
throw new \Exception(
sprintf("Can't create Document due to following: \n %s", $out->getErrorOutput())
);
}
$justToAutoload = $this->tryInstantiate($docDefinition);
$this->log->info($justToAutoload);
return InputHandler\InputHandler::getClassShortcutNotation($docDefinition);
}
Inside the debugging fn tryInstantiate() I tried several things, unregistering autoloaders, re-including composer's (app/autoload.php)
protected function tryInstantiate(DocumentType $docDefinition)
{
$fqcn = "\\" . $this->getDocumentFqcn($docDefinition);
$log = $this->log;
$functions = spl_autoload_functions();
foreach($functions as $function) {
spl_autoload_unregister($function);
}
$newLoader = include $this->kernel->getRootDir() . '/autoload.php';
$newLoader->register(true);
$log->info('tryInstantiate');
// spl_autoload_register(function ($className) use ($fqcn, $log) {
// if ($className == $fqcn) {
// $log->info("Loading: " . $className);
// $baseDir = $this->kernel->getRootDir() . '/../src';
// $classFile = $baseDir . str_replace('\\', DIRECTORY_SEPARATOR , $fqcn) . '.php';
// include $classFile;
// }
// }, true, true);
//$fqcn = str_replace('\\', '\', $fqcn);
return $test = new \DocDigital\Bundle\DocumentBundle\Entity\CustomDocument\Test();
die(var_dump($test));
return new $fqcn();
try {
return $deletMe = new \DocDigital\Bundle\DocumentBundle\Entity\CustomDocument\Test1();
return new $fqcn();
} catch (\Exception $exc) {
sprintf("Can't instantiate %s due to the following: \n %s", $fqcn, $exc->getTraceAsString());
}
}
always with the same result:
php.CRITICAL: Fatal Error: Class 'bundle\Entity\namespace\Test' not found
Any help is appreciated.
Thanks!
I'm trying to run a Symfony task but when i try to instantiate a class i get a fatal error.
The class is located in
Apps
MyApp
lib
My code is as follows
protected function execute($arguments = array(), $options = array())
{
$this->reloadAutoload();
// initialize the database connection
$databaseManager = new sfDatabaseManager($this->configuration);
$connection = $databaseManager->getDatabase($options['connection'])->getConnection();
// Get file from dir
if(!in_array($arguments['filename'] . $this->fileExt, scandir($this->path))) {
$this->logSection('Import CSV', 'File doesn\'t exist.', null, 'ERROR');
return;
}
$path = $this->path . '/' . $arguments['filename'] . $this->fileExt;
if(class_exists('CsvReader')) {
$csvReader = new CsvReader($path);
} else {
$this->logSection('Import CSV', 'Class doesn\'t exist.', null, 'ERROR');
return;
}
// add your code here
$this->logSection('Import CSV', 'All content imported.');
}
If there is anything i'm missing then let me know and i'll amend my question.
Thanks.
There are a couple things that might be preventing you from calling a class in your app:
You need to refresh your cache with php symfony cc
Your Symfony autoloader fails to find your class because the filename does not end with .class.php
Source: Documentation
I am developing in Drupal and using the php code from the Google Drive SDK that is supposed to download a file:
/**
* Download a file's content.
*
* #param Google_DriveService $service Drive API service instance.
* #param File $file Drive File instance.
* #return String The file's content if successful, null otherwise.
*/
function downloadFile($service, $file) {
$downloadUrl = $file->getDownloadUrl();
if ($downloadUrl) {
$request = new Google_HttpRequest($downloadUrl, 'GET', null, null);
$httpRequest = Google_Client::$io->authenticatedRequest($request);
if ($httpRequest->getResponseHttpCode() == 200) {
return $httpRequest->getResponseBody();
} else {
// An error occurred.
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
It is returning a successful response code of 200 but I cannot tell that it has actually done anything. However, I can tell from observing my LAN connection status that something of the right size in bytes is being downloaded. I just don't know where it is ending up. I am using Acquia Dev Desktop so I am running the website on my PC, but I cannot find where in the website folder the downloaded file is ending up if it is indeed being stored. I then tried another function that I found here and got similar results. Can someone more familiar with this explain what is happening?
function GetFile($service, $fileId) {
$fileVars = null;
try {
/*
* Retrieve metadata for the file specified by $fileId.
*/
$file = $service->files->get($fileId);
$fileVars = get_object_vars($file);
/*
* Retrieve the file's content using download URL specified in metadata.
*/
$downloadUrl = $file->getDownloadUrl();
error_log('Download URL file from Drive: ' . $downloadUrl);
if ($downloadUrl) {
$request = new Google_HttpRequest($downloadUrl, 'GET', null, null);
$httpRequest = Google_Client::$io->authenticatedRequest($request);
error_log(print_r($httpRequest, 1));
if ($httpRequest->getResponseHttpCode() == 200) {
$content = $httpRequest->getResponseBody();
$fileVars['content'] = $content?($content):'';
} else {
// An error occurred.
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
} catch (apiServiceException $e) {
/*
* Log error and re-throw
*/
error_log('Error retrieving file from Drive: ' . $e->getMessage());
throw $e;
}
return json_encode($fileVars);
}
This method returns the following results:
{"alternateLink":"https:\/\/docs.google.com\/file\/d\/0B6ahcE1NPpIaMTJzcFRLMnNiYU0\/edit?usp=drivesdk","appDataContents":false,"createdDate":"2013-12-05T21:05:03.026Z","defaultOpenWithLink":null,"description":"Flashum mp4","downloadUrl":"https:\/\/doc-0g-50-docs.googleusercontent.com\/docs\/securesc\/apic76cj8gku48a9ogarn9khpku0s46q\/gc9ck66nc600ebdk0ak9f58gkthnnacm\/1386345600000\/08295678552528470768\/15372451357194678536\/0B6ahcE1NPpIaMTJzcFRLMnNiYU0?h=16653014193614665626&e=download&gd=true","editable":true,"embedLink":"https:\/\/video.google.com\/get_player?ps=docs&partnerid=30&docid=0B6ahcE1NPpIaMTJzcFRLMnNiYU0&BASE_URL=https:\/\/docs.google.com\/","etag":"\"maCRbN5nR56FjQPLihEiz9nzpho\/MTM4NjI3NzUwNDU1MA\"","explicitlyTrashed":null,"exportLinks":null,"fileExtension":"mp4","fileSize":"788456","headRevisionId":"0B6ahcE1NPpIaeVJ5b3RxdExvamlDdWNrcGFvWXdvaWg3VU5JPQ","iconLink":"https:\/\/ssl.gstatic.com\/docs\/doclist\/images\/icon_11_video_list.png","id":"0B6ahcE1NPpIaMTJzcFRLMnNiYU0","imageMediaMetadata":null,"indexableText":null,"kind":"drive#file","labels":{"hidden":false,"restricted":false,"starred":false,"trashed":false,"viewed":false},"lastModifyingUser":{"displayName":"C. David Young","isAuthenticatedUser":false,"kind":"drive#user","permissionId":"08295678552528470768","picture":{"url":"https:\/\/lh6.googleusercontent.com\/-tjPzr0pfd_4\/AAAAAAAAAAI\/AAAAAAAAAWc\/DZtQHXrxkgQ\/s64\/photo.jpg"}},"lastModifyingUserName":"C. David Young","lastViewedByMeDate":null,"md5Checksum":"00701d2dd7a1b99e8ebb68cf62305b0d","mimeType":"application\/video","modifiedByMeDate":null,"modifiedDate":"2013-12-05T21:05:04.550Z","openWithLinks":null,"originalFilename":"charlesdavidyoung#gmail.com#test.mp4","ownerNames":["C. David Young"],"owners":[{"displayName":"C. David Young","isAuthenticatedUser":false,"kind":"drive#user","permissionId":"08295678552528470768","picture":{"url":"https:\/\/lh6.googleusercontent.com\/-tjPzr0pfd_4\/AAAAAAAAAAI\/AAAAAAAAAWc\/DZtQHXrxkgQ\/s64\/photo.jpg"}}],"parents":[{"id":"0B6ahcE1NPpIaQlMyWFBPamZIeTA","isRoot":false,"kind":"drive#parentReference","parentLink":"https:\/\/www.googleapis.com\/drive\/v2\/files\/0B6ahcE1NPpIaQlMyWFBPamZIeTA","selfLink":"https:\/\/www.googleapis.com\/drive\/v2\/files\/0B6ahcE1NPpIaMTJzcFRLMnNiYU0\/parents\/0B6ahcE1NPpIaQlMyWFBPamZIeTA"}],"quotaBytesUsed":"788456","selfLink":"https:\/\/www.googleapis.com\/drive\/v2\/files\/0B6ahcE1NPpIaMTJzcFRLMnNiYU0","shared":true,"sharedWithMeDate":null,"thumbnail":null,"thumbnailLink":"https:\/\/lh4.googleusercontent.com\/Ja2DZ3vzXSTn7kY_xY8VmC2N7nCeBrbvnkr-lO4GbMuOmpETwLAYlaC7qr5fOpBTTQ=s220","title":"charlesdavidyoung#gmail.com#test.mp4","userPermission":{"additionalRoles":null,"authKey":null,"etag":"\"maCRbN5nR56FjQPLihEiz9nzpho\/8jq33BWTNkV1S9Wn1TTkFYEVpVc\"","id":"me","kind":"drive#permission","name":null,"photoLink":null,"role":"writer","selfLink":"https:\/\/www.googleapis.com\/drive\/v2\/files\/0B6ahcE1NPpIaMTJzcFRLMnNiYU0\/permissions\/me","type":"user","value":null,"withLink":null},"webContentLink":"https:\/\/docs.google.com\/uc?id=0B6ahcE1NPpIaMTJzcFRLMnNiYU0&export=download","webViewLink":null,"writersCanShare":true,"copyable":true,"content":null}
If you pass to your script a document id it should return you a download link under the field exportLinks. The fact that your exportLinks is null means that you cannot download the file (permissions?).