Jump to content

All Activity

This stream auto-updates

  1. Today
  2. I don't really want to guess at what the application is, but SaaS would entail you hosting the application on your infrastructure and the customer using the functionality you provide within the app as an end user. There's no subterfuge involved in it. If there's some reason that a user would believe they were tricked in some way, then it's not SaaS.
  3. @gizmola it would seem that the Software as a Service model would be more in line with my thinking (since I fear my code being co-opted). How is this best implemented? In simple terms, if the customer wants users to complete a form, would I just re-direct them to a form on MY server? Wouldn't that seem a bit suspicious if detected?
  4. We are a Communication Platform as a Service (CPaaS) designed to streamline how businesses connect with customers across multiple channels. Our flexible, cloud-based solutions integrate communication tools directly into your apps or websites, enabling real-time engagement. Looking for a Tech Lead/Architect who is ready to take responsibility and assume technical leadership and architectural decision-making on our high-load platform. WHAT YOU WILL BE DOING: Developing architecture for new system modules that ensure high performance and scalability of high-load systems. Implementing horizontal and vertical scaling strategies to ensure stable system operation under increasing load. Optimizing system performance. Analyzing and optimizing database queries (MySQL, PostgreSQL) to ensure maximum performance. Coordinating the technical team, distributing tasks among developers, and monitoring their execution. Ensuring effective interaction between different technical teams, as well as between technical and non-technical stakeholders. Implementing and optimizing development processes, ensuring compliance with code quality standards. Critically analyzing and approving architectural decisions, making final decisions on task implementation. YOUR COMPETENCIES: Experience working with high-load systems. High proficiency in PHP (Laravel, Symfony) Deep knowledge of databases (MySQL, PostgreSQL) and query optimization. Experience with queue processing tools (Kafka, RabbitMQ) and caching (Redis). Experience working with Kubernetes and Docker. Experience with Linux platform (debugging and log analysis). Understanding of parallelism principles in PHP and the ability to emulate threads to ensure efficient process operation. Experience in designing and implementing architecture for high-load systems. Strong communication skills for effective interaction with stakeholders. Ability to critically evaluate task acceptance criteria and ensure compliance with code quality standards. WII BE A PLUS IF YOU HAVE: Experience in the telecom industry. Knowledge of SMPP and TCP/IP protocols (telecommunications systems). Experience in reengineering legacy systems. Knowledge of other languages. English at least B1. WE OFFER: You'll have the ultimate authority on technical decisions, shaping the future of our high-load platform. Skilled team. Mature management. Remote work; Competitive salary; 24 days of paid vacation. 3 days off if you need an emotional reboot. Holidays, vacation, sick leaves — according to the local legislation. Other benefits.
  5. If you're developing code for someone at a cost, typically they would expect to own that code or a license to that code in return for the payment they are making to you. Generally speaking, the "data" for a system is the property of the customer/business using your system. It's not unusual for companies to provide a separate "maintenance" agreement that covers a period of time, wherein the customer would pay you an amount to enhance it and fix bugs. You also could provide the system in a Software as a Service model, where you host the system and code, and provide the customer access to the application, without otherwise providing the system level access they would need to even see the code. As far as pricing, there are many ways to estimate and cost projects. Understandably companies tend to like to know a price for something, so you need to have a decent idea of what amount of time it will take you to build the features. You make this estimation in "ideal" time, which is the amount of time any feature might take if you are head-down and fully productive. Then add a reasonable amount of overhead to your ideal estimate (anywhere from 10-35% is not uncommon). Determine a reasonable market rate for your time, and in combination, you'll have a "by feature" estimate you can utilize as a fix bid, with associated milestones. Any project like this should involve a contract.
  6. In order to "upload" a file to a server, and make that "quicker" you need to have optimized the size of the photo on your workstation. PHP doesn't come into it.
  7. @Strider64 I think my intention (at first, anyway) was to increase upload speed (especially if a few images were involved) and avoid upload size maximum limits (that the server /hosting service enforces). Will this actually address the issue? Is there another reliable resolution?
  8. Yesterday
  9. I use Intervention using composer which is a very handy utility. // Load the image $image = Image::make($image_path); // Resize the image $image->resize(2048, 1365, function ($constraint) { $constraint->aspectRatio(); $constraint->upsize(); }); // Save the new image $image->save($image_path, 100); You can do other image manipulation with Intervention as well and pretty easily. I don't know if this is something you are looking for?
  10. Some time ago I was playing with PHP code to minimize the size of images. My primary purpose was to reduce the file size so that uploading would be quicker and thereby encounter fewer instances of exceeding the upload limits of the hosting server. It recently occurred to me that this was a futile exercise because once PHP was involved, the files at full size had already engaged with the server. Am I correct in my assumption? Is there a reliable way to approach what I had initially intended?
  11. I was asked to create a form and database system for a local entrepreneur and need some business advice and acceptable practices input. From the technical side, I'm concerned about keeping my intellectual property secure and private. If I allow the 'customer' to have access to the files I create, I may not be needed long term. How can I maintain control over the code that I write? And the database that it populates? From a business standpoint, are there generally accepted guidelines for ownership of intellectual property? I also have questions regarding compensation. Is there a ballpark of generality based on hours invested or (USA) dollars for such an endeavor or it's pieces?
  12. Most systems I've seen will write the file to a temporary directory on the server, zip it and serve the zip to the user, then delete the file from the temporary directory. But honestly requinix is right - just direct the user in a new tab to the page that gathers the data and presents it. If I'm not mistaken, the tab itself will close and your user will get the browser's download window.
  13. Looks like requinix responded while I was considering my answer, which would be a YES. ITEM 1 is easy enough. ITEM 2 would require some research (for me, anyway) but should be do-able since PHP can go to a directory and find the file you want to use. ITEM 3 can also be done. I forget the methodology, but I did create a page that allowed me to download files from <a> links; a few modifications and your requirements would be met. As for wanting to NOT have the file on the server, did you want PHP to write the script and ZIP it every time it's needed? I suppose it could be done, but a cumbersome way of making sure nobody sees the script on the server, yet they can grab it through the browser.
  14. Why use AJAX at all? Simply send the browser to the "page" which (immediately) serves the download.
  15. Hey guys, I have a script I’m working on, and I was curious if I can do the following: 1. user clicks button on browser, that sends a request to the server using ajax 2. the server creates a zip file and stores it in php://memory 3. the browser get the needed information to initiate a download of the zip file. can this be done? I suspect I have to physically save the file on the server, and delete it after; which I would like to avoid
  16. Last week
  17. wildcard characters % and _ are only used with a LIKE comparison in a query. if your first query produces any result, it means that you managed to store the % characters in with the data in the database table. preg_match() is a php function. you cannot put it a query to match data in the database table. this query would be producing an sql error. are you using exceptions for errors for the sql queries (this is the default setting now in php8+)? MySql does have regular expressions. see this link - https://dev.mysql.com/doc/refman/8.4/en/regexp.html the regex pattern you came up with matches a string with exactly 3 decimal digits. your stated example is to match 2 digits. which is it and can it vary? what exactly is the overall top-level task you are trying to accomplish, because using regex pattern matching is slow and cannot use indexes, so is a poor choice when you have large amounts of data? lastly, do NOT put dynamic data values directly into sql queries, where any sql special character in a value can break the sql query syntax. use a prepared query instead. if it seems like using the mysqli extension is overly complicated and inconsistent, especially when dealing with prepared queries, it is. this would be a good time to switch to the much simpler and better designed PDO extension.
  18. Lets say you have the following values: 1341 1234 4567 12 1 I'm trying to right a preg_match which will only return true for '34' thus only matching if 2 digits. This is what I have, but it is also matching 1341 and 1234. I may have something after it too. currently my query is as follows: if(isset($_GET['search'])){ $cari = $_GET['search']; $data = mysqli_query($con,"select *** where (table1.test2 = '%".$search."%' or left(table1.test3,3) = '%".$search."%') and date(table.created_date) = '" .$today. "'" but after I change to this following: if(isset($_GET['search'])){ $cari = $_GET['search']; $data = mysqli_query($con,"select *** where (table1.test2 = preg_match('/^[0-9]{3}$/',$search) or left(table1.test3,3) = preg_match('/^[0-9]{3}$/',$search);) and date(table.created_date) = '" .$today. "'" failed. do you have any idea how to construct the preg_match ?
  19. the problem is solved. thank you
  20. You are reinventing the wheel for no good reason. Your database wrapper functions are simplistic and have many issues with them. Just looking at the code here are the things you are trying to accomplish: mysql connection setup and management Query building Query execution and result set fetching There are already a number of well designed PDO wrapper libraries out there. I recommend using Doctrine2 DBal. Doctrine2 is an Object Relational Mapping library that is used by many projects, and is the standard ORM integrated into the Symfony framework. Doctrine2 was architected to utilize a "Database Abstraction Layer" (DBAL) and layers the ORM features on top of that, but you can easily use DBAL by itself. I did exactly that in this simple example web application (rowCloner) I created to illustrate one particular feature of DBAL. By looking at that code, you have an example of how to setup a connection, make a query with parameters and get results. DBAL provides you all the things you need to make queries of different types when you require that. It also has a well designed Query Builder which is fluent and alllows you to create any type of query you want. You can further abstract DBAL with your own classes as I did with the rowCloner class in the example app.
  21. Yes, using fetch is easier in my opinion and here's an example of a page on my website (not the full code): 'use strict'; class ProductManager { constructor() { // DOM Elements this.category = document.querySelector('#category'); this.container = document.querySelector('.main_manager_container'); this.sidebar = document.querySelector('.sidebar_pages'); this.lightbox = document.querySelector('.lightbox'); // Pagination Configurations this.current_page = 1; this.per_page = 3; this.offset = 0; this.total_pages = 0; // Data fetched from the database this.database_data = { 'category': 'images', 'current_page': this.current_page, 'per_page': this.per_page, 'total_count': 0, 'offset': this.offset }; this.pages = [{}]; // Binding `this` context to methods this.categoryUISuccess = this.categoryUISuccess.bind(this); this.paginationUISuccess = this.paginationUISuccess.bind(this); this.resetLinks = this.resetLinks.bind(this); } // Handle fetch errors handleErrors(response) { if (!response.ok) { throw (response.status + ' : ' + response.statusText); } return response; } // Update the UI upon successfully fetching gallery category data async categoryUISuccess(parsedData) { this.clearContainer(); console.log('parsed data', parsedData); // Close the lightbox if it's open this.exitLightbox(); parsedData.forEach((slide, index) => { this.createSlide(slide, index); }); this.addImageListeners(); } // Clear all child elements of the container clearContainer() { while (this.container.firstChild) { this.container.removeChild(this.container.firstChild); } } // Function to truncate text and add a "More..." link addReadMore(paragraph) { const fullText = paragraph.textContent; const truncatedText = fullText.slice(0, 300) + '...'; // Adjust the number of characters as needed const moreLink = document.createElement('span'); moreLink.textContent = ' More...'; //moreLink.style.color = 'blue'; //moreLink.style.cursor = 'pointer'; paragraph.textContent = truncatedText; paragraph.appendChild(moreLink); paragraph.dataset.fullText = fullText; moreLink.addEventListener('click', function() { if (paragraph.textContent.includes('...')) { paragraph.textContent = paragraph.dataset.fullText; moreLink.textContent = ' Less'; } else { paragraph.textContent = truncatedText; paragraph.appendChild(moreLink); } }); } equalizeArticleHeights() { const articles = document.querySelectorAll('.article'); let maxHeight = 0; // Find the tallest article articles.forEach(article => { if (article.offsetHeight > maxHeight) { maxHeight = article.offsetHeight; } }); // Set all articles to the height of the tallest one articles.forEach(article => { article.style.minHeight = `${maxHeight}px`; }); } // Create individual gallery slides createSlide(slide) { const article = this.createElementWithClass('section', 'article'); this.container.appendChild(article); const largeImage = this.createElementWithClass('a', 'largeImage'); largeImage.href = "#"; largeImage.setAttribute('data-image', slide.image_path); // Updated part: Attach event listener to largeImage largeImage.addEventListener('click', (event) => { event.preventDefault(); // Prevent default anchor action this.handleImageClick(largeImage); }); article.appendChild(largeImage); console.log('largeImage', largeImage); const image = this.createElement('img', { src: slide.thumb_path, alt: slide.content, loading: 'lazy', class: 'imageStyle' }); largeImage.appendChild(image); const heading = this.createElementWithClassAndContent('h2', 'articleHeading', slide.heading); article.appendChild(heading); const paragraph = this.createElementWithClassAndContent('p', 'articleText', slide.content); article.appendChild(paragraph); // Truncate text and add "More..." link this.addReadMore(paragraph); this.equalizeArticleHeights(); } // Utility function to create an HTML element with attributes createElement(tag, attributes = {}) { const element = document.createElement(tag); Object.entries(attributes).forEach(([key, value]) => { element.setAttribute(key, value); }); return element; } createElementWithClass(tag, className) { const element = this.createElement(tag); element.className = className; return element; } createElementWithClassAndContent(tag, className, content) { const element = this.createElementWithClass(tag, className); element.textContent = content; return element; } // Add click event listeners to images to open in lightbox addImageListeners() { const images = document.querySelectorAll('img'); images.forEach(image => { image.addEventListener('click', () => this.handleImageClick(image)); }); } // Add click event listener to lightbox to close it addLightboxListener() { this.lightbox.addEventListener('click', () => { this.exitLightbox(); }); } // Updated handleImageClick to include title and content handleImageClick(anchor) { const largeImageUrl = anchor.getAttribute('data-image'); // Get large image URL const title = anchor.getAttribute('data-title'); // Assuming you add this attribute const content = anchor.getAttribute('data-content'); // Assuming you add this attribute // Clear and set up the lightbox this.lightbox.innerHTML = ''; // Clear previous content // Create and display the large image const largeImage = this.createElement('img', { src: largeImageUrl }); largeImage.classList.add('lightbox-image'); this.lightbox.appendChild(largeImage); // Create and append the title if (title) { const imageTitle = this.createElementWithClassAndContent('h2', 'lightbox-title', title); this.lightbox.appendChild(imageTitle); } // Create and append the content if (content) { const imageContent = this.createElementWithClassAndContent('p', 'lightbox-content', content); this.lightbox.appendChild(imageContent); } // Show the lightbox this.lightbox.style.display = 'block'; } // Close the lightbox exitLightbox() { this.lightbox.style.display = 'none'; // Hide the lightbox this.lightbox.innerHTML = ''; // Clear the lightbox content } // Handle errors when fetching gallery category data fails categoryUIError(error) { console.log("Database Table did not load", error); } // Send a request to the server to fetch images async createImageRequest(url, succeed, fail) { try { const response = await fetch(url, { method: 'POST', // or 'PUT' body: JSON.stringify(this.database_data), }); this.handleErrors(response); const data = await response.json(); succeed(data); } catch (error) { fail(error); } } // Clear all pagination links resetLinks() { /* Remove Links For Screen (cleanup) */ while (this.sidebar.firstChild) { this.sidebar.removeChild(this.sidebar.firstChild) } } // Update the UI with the received pagination data async paginationUISuccess(parsedData) { this.resetLinks(); this.database_data.offset = await parsedData.offset; this.total_pages = Math.ceil(this.database_data.total_count / this.database_data.per_page); /* Create the Display Links and add an event listener */ this.pages = [{}]; /* * Creating the array of page object(s) */ for (let x = 0; x < this.total_pages; x++) { this.pages[x] = {page: x + 1}; } this.pages.forEach(link_page => { const links = document.createElement('div'); links.className = 'links'; this.sidebar.appendChild(links); /* * Add event listener for the links */ links.addEventListener('click', () => { this.database_data.current_page = link_page.page; this.createRequest('portfolioPagination.php', this.paginationUISuccess, this.paginationUIError); }); const pageText = document.createElement('p'); pageText.className = 'linkStyle'; pageText.id = 'page_' + link_page.page; pageText.textContent = link_page.page; links.appendChild(pageText); if (this.database_data.current_page === link_page.page) { links.style.backgroundColor = "#00b28d"; } }) await this.createImageRequest('portfolioGetImages.php', this.categoryUISuccess, this.categoryUIError); } // Handle errors when fetching pagination data fails paginationUIError(error) { console.log("Database Table did not load", error); } // Send a request to the server async createRequest(url, succeed, fail) { try { const response = await fetch(url, { method: 'POST', // or 'PUT' body: JSON.stringify(this.database_data), }); this.handleErrors(response); const data = await response.json(); //console.log('count', data); succeed(data); } catch (error) { fail(error); } } // Send a request to get the total number of images in a category async updateTotalCountAndPagination() { await this.createRequest('getTotalCount.php', this.totalCountUISuccess.bind(this), this.totalCountUIError.bind(this)); } // Update the UI upon successfully fetching the total count totalCountUISuccess(parsedData) { this.database_data.total_count = parsedData.total_count; this.createRequest('portfolioPagination.php', this.paginationUISuccess.bind(this), this.paginationUIError.bind(this)); } // Handle errors when fetching the total count fails totalCountUIError(error) { console.log("Database Table did not load", error); } // Add event listeners to DOM elements bindEvents() { this.category.addEventListener('change', () => { this.database_data.current_page = 1; this.database_data.category = this.category.value; this.updateTotalCountAndPagination(); }); document.addEventListener('DOMContentLoaded', () => { this.createRequest('portfolioPagination.php', this.paginationUISuccess.bind(this), this.paginationUIError.bind(this)); }); } // Initialization function init() { this.addLightboxListener(); this.updateTotalCountAndPagination(); this.bindEvents(); } } const productManager = new ProductManager(); productManager.init(); and the main PHP file: <?php // Load the configuration settings and Composer's autoloader to manage dependencies. require_once __DIR__ . '/../config/clearwebconfig.php'; require_once "vendor/autoload.php"; // Import necessary classes from the clearwebconcepts namespace for error handling, database interaction, and image management. use clearwebconcepts\{ ErrorHandler, Database, ImageContentManager, }; // Create an instance of the ErrorHandler to handle exceptions throughout the script. $errorHandler = new ErrorHandler(); // Register the custom exception handler to delegate exception handling to the ErrorHandler class. set_exception_handler([$errorHandler, 'handleException']); // Initialize a Database instance and create a PDO connection for database access. $database = new Database(); $pdo = $database->createPDO(); // Placeholder for optional arguments that might be needed by the ImageContentManager. $args = []; // Create an instance of the ImageContentManager for managing image content in the specified portfolio gallery. $gallery = new ImageContentManager($pdo, $args, 'portfolio'); // Initialize an empty array to hold input data parsed from the request body. $database_data = []; try { /* * Attempt to retrieve and decode JSON input from the HTTP request body. * JSON_THROW_ON_ERROR ensures a JsonException is thrown in case of any decoding issues. */ $database_data = json_decode(file_get_contents('php://input'), true, 512, JSON_THROW_ON_ERROR); } catch (JsonException $e) { // Handle decoding errors silently; optional logging can be added here. } /* * Retrieve paginated image content from the ImageContentManager. * This method takes the number of items per page, the offset, the gallery type ('portfolio'), * and an optional category filter from the decoded input data. */ $send = $gallery->page( (int)$database_data['per_page'], (int)$database_data['offset'], 'portfolio', $database_data['category'] ); // Output the resulting image data to the client in JSON format. output($send); /** * Outputs the given data as a JSON response with HTTP 200 status. * * @param mixed $output The data to be encoded and sent in the HTTP response body. */ function output($output): void { http_response_code(200); try { // Encode the output data as JSON and send it to the client. echo json_encode($output, JSON_THROW_ON_ERROR); } catch (JsonException) { // Fail silently on JSON encoding errors; optional error handling can be added here. } } and the page itself: https://www.clearwebconcepts.com/portfolio.php
  22. Every browser has a DOM built into it which represents the HTML elements and styles the browser has created from the underlying HTML/CSS and Javascript code. To manipulate the page, once the HTTP response from the server is complete, you need to use javascript. That is not inherently dangerous, given the limitations that are built into browsers, and standard security models like CORS which you can read more about here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS So yes, you want to use "ajax" which is a generalized term for using javascript functions (should use fetch at this point) to retrieve data, and from there to make updates to the DOM that is loaded.
  23. What specific commands are you running, and what specific error message(s) are you receiving?
  24. very nice.. correct that it will be similar like excel spreadsheet. it is because the user is not familiar yet with web application. I didn't think about that before. so, I will make a category_id column and it will be available in all tables. but I think I just need one table only if the category_id is used to split each product. I mean it will be option columns. Currently we have only 3 category products. but how to arrange it so that it can properly directly insert into the columns i.e. testx untul testx2 ?
  25. Earlier
  26. awesome.. i will try. thank you
  27. Use sprintf. You can convert the number to whatever format you want to enforce. $test3 = sprintf('%04d',$test3key);
  28. Let's say I want to construct some input fields using this for each loop : foreach($_POST['test3'] as $key => $test3key){ $test3 = $test3key; $test31 = $_POST['test31'][$key]; $test32 = $_POST['test32'][$key]; if (!empty($test3key) && !empty($test31) && !empty($test32)) { // insert sql } } The data for example is test3 = 0033, test31 = 1; test32 is 1,000 In this particular case, the test3 will get converted to just 33 in the database table column. The test3 column type in the database is text. I want to prevent the leading zero removal. How can I accomplish this?
  29. you are trying to store the data like it is in a spreadsheet, not a database. doing this makes all the code and queries to perform any action on the data overly complicated. it appears that each html table section is for a different type/category of products? within each type/category of product, the testx field is the item id, the testx1 field is the quantity, and the testx2 field is the total? if so, when you store the data in the detail table, you should have a category_id column (that indicates which html table section that data is for), an item_id column, a quantity column, and a total column.
  1. Load more activity
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.